#include "SkillPart.h"
#include "base/core/gamemath.h"
#include "Scene/SceneMgr.h"
#include "base/core/log.h"
#include "base/core/random.h"
#include "Common/Utility/ServerTime.h"
#include "Common/TableData/AttributeSuppressCfg.h"
#include "Common/Utility/AccountUtility.h"
#include "Common/TableData/FunctionunlockFunctionUnlockCfg.h"
#include "Character/Player.h"
#include "BuffPart.h" 
#include "MovePart.h"

#include "Common/CharacterDefine.h"
#include "base/core/Profiler.h"
#include "Character/CreatureMgr.h"
#include "../Server/ServiceMgr.h"
#include "Common/AttrMgr/AttrMgr.h"
#include "npc/Npc.h"
#include "Character/horse/HorsePart.h"

//技能Id前置段
#define bulletTimeIdPre  1000000000

const float g_constSKillAdjust = 0.5;
const int32_t g_constDamagePer = -8500;  //伤害调整百分比最小值

const float g_constDodgePara = 0.2;    //闪避系数
const float g_constThughnessPara = 3;  //暴击抵抗

SkillPart::SkillPart()
{
	m_mapskills.clear();

	m_mapMsgfunc[CLIENT_TO_LOGIC_SKILL_USE] = &SkillPart::C2UseSkill;
	m_mapMsgfunc[CLIENT_TO_LOGIC_SKILL_LEVEL_UP_REQ] = &SkillPart::C2LevUpSkill;

	m_mapMsgfunc[CLIENT_TO_LOGIC_SKILL_STOP] = &SkillPart::C2StopUseSkill;

	m_mapMsgfunc[CLIENT_TO_LOGIC_SKILL_TARGETS] = &SkillPart::C2SyncSkillTargets;

	m_mapMsgfunc[CLIENT_TO_LOGIC_BUFF_LIST] = &SkillPart::C2GetBuffList;

	m_nNumber = 0;
}

SkillPart::~SkillPart()
{

}

bool SkillPart::Init(Creature *pMaster, uint32_t partType, CharacterDBInfo* pCharacterDB /* = nullptr */)
{
	Part::Init(pMaster, partType);
	//m_curBulletIdCount = 0;
	if (nullptr == pCharacterDB)
	{
		return true;
	}

	uint64_t cd = 0;
	if (pCharacterDB->has_skilldata())
	{
		//后期对玩家加判断
		CharacterDBSkillData pSkillData = pCharacterDB->skilldata();
		CharacterDBSkillItem Skillitem;
		for (int32_t i = 0; i < pSkillData.skilllist_size(); i++)
		{
			Skillitem = pSkillData.skilllist(i);
			cd = Skillitem.cd(); //- g_GetGlobalServerTime()->Tick();
			cd = cd  > 0 ? cd : 0;
			AddSkill(Skillitem.skillid(), Skillitem.skilllevel(), cd,0,false,false,enSkillSaveType_SaveDB);
		}
	}
	else
	{
		const RoleBornCfgInfo *pRoleBornCfg = g_GetRoleBornCfg((uint8_t)m_pMaster->GetAttr(C_PROF), (uint8_t)m_pMaster->GetAttr(C_GENDER));
		if (!pRoleBornCfg)
		{
			LogErrFmtPrint("skillpart init borncfg null, cant't init skillId, cid:%d", m_pMaster->GetCid());
			return false;
		}
		//pRoleBornCfg->vec_actSkill;
		for (uint32_t i = 0; i < pRoleBornCfg->vec_actSkill.size(); i++)
		{
			AddSkill(pRoleBornCfg->vec_actSkill[i], 1, 0, 0, false, false, enSkillSaveType_SaveDB);
		}

		////新号有初身buff,给加上
		//for (uint32_t i = 0; i < pRoleBornCfg->vec_actBuff.size(); ++i)
		//{
		//	if (pRoleBornCfg->vec_actBuff[i]>0)
		//	{
		//		AddStateBag(pRoleBornCfg->vec_actBuff[i], 1, m_pMaster);
		//	}
		//}
	}
	return true;
}


bool SkillPart::UnInit()
{
	g_GetTimerAxis()->KillAllTimer(this);
	mapSkillFightInfo::iterator iter = m_mapSkillFightInfo.begin();
	for (; iter != m_mapSkillFightInfo.end(); ++iter)
	{
		RecyleSkill(iter->second);
	}
	m_mapSkillFightInfo.clear();


	Part::UnInit();
	m_mapskills.clear();


	return true;
}


SkillBase * SkillPart::FactoryCreateSkillFightInfo(uint32_t skillID)
{
	const SkillCfg* pConfig = NULL;
	pConfig = g_GetSkillMgr()->GetSkillCfg(skillID);
	if (!pConfig)
	{
		return NULL;
	}
	m_nNumber = (m_nNumber+1) % 210000000000;
	if (m_nNumber==0)
	{
		m_nNumber = 1;
	}

	if (pConfig->processTypes != process_bullet && pConfig->processTypes != Process_SomeBullet)
	{
		//除了子弹类技能，不容许同一个技能出现两个实体
		SkillBase * pFightSkill = GetFightSkillInfo(skillID);
		if (pFightSkill)
		{
			RemoveSkillFightInfo(pFightSkill->GetGlobelID());
		}
	}
	
	//获取技能
	SkillBase * pSkill = NULL;
	SkillFightType type = SkillFightType_SkillBase;
	switch (pConfig->processTypes)
	{
	case process_bullet:
	case Process_SomeBullet:
	{
		pSkill = g_GetSkillMgr()->m_pBulletPool->MallocObj();
		type = SkillFightType_SkillBullet;
	}
	break;
	case process_shadowStrike:
	{
		 pSkill = g_GetSkillMgr()->m_pShadowPool->MallocObj();
		type = SkillFightType_SkillShadowStrike;
	}
		break;
	case process_flash:
	{
		pSkill = g_GetSkillMgr()->m_pFlashPool->MallocObj();
		type = SkillFightType_SkillFlash;
	}
		break;
	case process_summon:
	{
		pSkill = g_GetSkillMgr()->m_pSummonPool->MallocObj();
		type = SkillFightType_SkillSummon;
	}
		break;
	case Process_Tuxi:
	{
		pSkill = g_GetSkillMgr()->m_pTuXiPool->MallocObj();
		type = SkillFightType_SkillTuXi;
	}
		break;
	case Process_Collide:
	{
		pSkill = g_GetSkillMgr()->m_pChongZhungPool->MallocObj();
		type = SkillFightType_Collide;
	}
		break;
	case Process_Gouzi:
	{
		 pSkill = g_GetSkillMgr()->m_pGouziPool->MallocObj();
		type = SkillFightType_Gouzi;
	}
		break;
	case Process_Relive:
	{
		pSkill = g_GetSkillMgr()->m_pRelivePool->MallocObj();
		type = SKillFightType_Relive;
	}
		break;
	case Process_SkillSummon:
	{
		pSkill = g_GetSkillMgr()->m_pSomeSummonPool->MallocObj();
		type = SkillFightType_SomeSummon;
	}
		break;
	case Process_SomeBulletOnePoint:
	{
		pSkill = g_GetSkillMgr()->m_pSomeBulletOnePointPool->MallocObj();
		type = SkillFightType_SomeBulletOnePoint;
	}
		break;
	case Process_SomePointDelayAoe:
	{
		pSkill = g_GetSkillMgr()->m_pSomePointDelayAoePool->MallocObj();
		type = SkillFightType_SomePointDelayAoe;
	}
		break;
	case Process_MoveAOE:
	{
		pSkill = g_GetSkillMgr()->m_pSkillMoveAoePool->MallocObj();
		type = SkillFightType_MoveAOE;
	}
		break;
	case Process_SomeShareDamage:
	{
		pSkill = g_GetSkillMgr()->m_pShareDamagePool->MallocObj();
		type = SkillFightType_ShareDamegeSkill;
	}
		break;
	case Process_LockSomeTarget:
	{
		pSkill = g_GetSkillMgr()->m_pLockTargetPool->MallocObj();
		type = SkillFightType_LockSomeTarget;
	}
		break;
	default:
	{
		pSkill = g_GetSkillMgr()->m_pBasePool->MallocObj();
	}
		break;
	}

	if (pSkill)
	{
		pSkill->Init(type, pConfig,m_nNumber, this);
		m_mapSkillFightInfo[m_nNumber] = pSkill;
	}
	else
	{
		LogDebugFmtPrint("new base error not enouth obj");
	}
	return pSkill;
}

SkillBase * SkillPart::GetSkillBySkillID(uint32_t skillID)
{
	mapSkillFightInfo::iterator iter = m_mapSkillFightInfo.begin();
	for (; iter != m_mapSkillFightInfo.end();++iter)
	{
		if (iter->second->IsSameSkill(skillID))
		{
			return iter->second;
		}
	}
	return NULL;
}

bool SkillPart::OnMsgHandle(uint32_t cmd, const char* data, uint32_t len)
{
	mapMsgFunc::iterator iter = m_mapMsgfunc.find(cmd);
	if (iter == m_mapMsgfunc.end())
		LogErrFmtPrint("msg dont exit in skillpart, cmd:%d", cmd);
	else
		(this->*m_mapMsgfunc[cmd])(data, len);

	return true;
}

stSkillInfo* SkillPart::GetSkillInfo(uint32_t skillId)
{
	mapSkillInfo::iterator iter = m_mapskills.begin();
	for (; iter != m_mapskills.end();++iter)
	{
		if (iter->second.IsSameSkill(skillId))
		{
			return &iter->second;
		}
	}
	return nullptr;
}

//获取技能实体,一个技能可能有多个战斗对像
SkillBase * SkillPart::GetFightSkillInfo(uint32_t skillId)
{
	mapSkillFightInfo::iterator iter = m_mapSkillFightInfo.begin();
	for (; iter != m_mapSkillFightInfo.end();++iter)
	{
		if (iter->second->GetSkillID() == skillId)
		{
			return iter->second;
		}
	}
	return nullptr;
}

bool SkillPart::SynOnLogin(PlayerClientInfo& playerInfo)
{
	SkillCell *pskill = nullptr;
	mapSkillInfo::iterator iter = m_mapskills.begin();
	for (; iter != m_mapskills.end(); iter++)
	{
		if (!iter->second._enSaveType == enSkillSaveType_SaveDB)
		{
			continue;
		}
		pskill= playerInfo.add_skills();
		pskill->set_skillid(iter->second._Id);
		pskill->set_skilllev(iter->second._level);
		int64_t tmp = iter->second._pSkillmeta->cd-(Time::Now().UnixMSec() - iter->second._cdTimeStamps);
		uint32_t leftCD = tmp > 0 ? tmp : 0;
		pskill->set_cd(leftCD);
	}
	return true;
}

void SkillPart::SynCreatureLevUp(CreaturesLevUp& clientLevInfo)
{
	if (m_pMaster->CreatureKind() == CREATURE_PLAYER)
	{
		if (m_pMaster->GetAttr(C_PROF) < ECHARACTER_PROF_WARRIOR || m_pMaster->GetAttr(C_PROF) > ECHARACTER_PROF_ARCHER)
			return;

		CreaturesLevUp::Player * cPlayer = clientLevInfo.mutable_character();
		SkillCell *pskill = nullptr;
		uint32_t prof = m_pMaster->GetAttr(C_PROF);
		uint32_t level = m_pMaster->GetAttr(C_LEVEL);

		const list<uint32_t> pskillLst = g_GetSkillMgr()->GetNewSkillLst(prof, level);
		if (pskillLst.empty())
			return;

		auto iter = pskillLst.begin();
		for (; iter != pskillLst.end(); iter++)
		{
			//if (!GetSkillInfo(*iter))  //有的技能就不用加
			{
			//	AddSkill(*iter, 1);
				stSkillInfo* pskillConfig=GetSkillInfo(*iter);
				if (pskillConfig)
				{
					if (!pskillConfig->_isUnLock)
					{
						pskill = cPlayer->add_skills();
						pskill->set_skillid(*iter);
						pskill->set_skilllev(1);
						pskill->set_cd(0);
						pskillConfig->_isUnLock = true;
					}
				}
				
			}
		}
	}
}

void SkillPart::OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{

}

void SkillPart::OnTimer(uint32_t nTimerID)
{
	//if (m_pMaster->IsDead())
	//{
	//	return;
	//}


	//if (nTimerID > cdTimeIdPre)
	//{
	//	KillTimedo(nTimerID);
	//	uint32_t skillId = nTimerID - cdTimeIdPre;
	//	stSkillInfo* pSkill = GetSkillInfo(skillId);
	//	if (pSkill)
	//		pSkill->_cdTimeStamps = 0;
	//	return;
	//}

	//mapSkillInfo::iterator skillIter = m_mapskills.find(nTimerID);
	//if (skillIter != m_mapskills.end())
	//{
	//	mapTimedoFunc::iterator iter = m_mapTimedofunc.find(skillIter->second.curState);
	//	if (iter == m_mapTimedofunc.end())
	//		return;
	//	(this->*m_mapTimedofunc[skillIter->second.curState])(nTimerID);
	//}
	//else
	//{
	//	lstBullet::iterator iter = m_lstBullet.begin();
	//	for (; iter != m_lstBullet.end(); iter++)
	//	{
	//		if (iter->Id == nTimerID)
	//		{
	//			FindCreatures(iter->pSkillmeta, iter->tartgetCid, iter->tartgetPos, 0, 0);
	//			m_lstBullet.erase(iter);
	//			//killTimedo(nTimerID);
	//			break;
	//		}
	//	}
	//}

	BEGIN_PROFILE("ontime");
	mapSkillFightInfo::iterator iter = m_mapSkillFightInfo.find(nTimerID);
	if (iter != m_mapSkillFightInfo.end())
	{
		iter->second->OnTime();
	}
	END_PROFILE();
}

//怪物ai调用使用技能接口
bool SkillPart::BeginCreatureUseSkill(uint32_t skillId, vecUint64_t& targetCids, const Point3<float> &dir, const Point3<float>& targetPos)
{
	stSkillInfo* pSkill = GetSkillInfo(skillId);
	if (!pSkill)
		return false;
	if (!IsCanUseSkill(skillId, &targetCids))
		return false;

	pSkill->_cdTimeStamps = Time::Now().UnixMSec();

	std::vector<SkillBase * > vTmp;  //有可能一个技能，能产生多个战斗
	if (pSkill->_pSkillmeta->processTypes == process_bullet || pSkill->_pSkillmeta->processTypes==Process_SomeBullet)
	{
		for (int i = 0; i < (int)targetCids.size(); ++i)
		{
			vector<CharIDType> vtargetList;
			vtargetList.push_back(targetCids[i]);
			//能使用，则生成战斗信息
			SkillBase * pSkillBase = FactoryCreateSkillFightInfo(skillId);
			if (!pSkillBase)
			{
				return false;
			}
			pSkillBase->SetSkillDir(dir);
			pSkillBase->SetTargetPos(targetPos);
			pSkillBase->SetTargetCidsList(vtargetList);
			vTmp.push_back(pSkillBase);
		}
	}
	else
	{
		SkillBase * pSkillBase = NULL;
		 pSkillBase = FactoryCreateSkillFightInfo(skillId);
		if (!pSkillBase)
		{
			return false;
		}

		pSkillBase->SetTargetPos(targetPos);
		pSkillBase->SetTargetCidsList(targetCids);
		pSkillBase->SetSkillDir(dir);

		vTmp.push_back(pSkillBase);
	}
	
	//if (pSkill->_pSkillmeta->processTypes == process_summon)
	//{
	//	vTmp[0]->SetSummonPos(targetPos);
	//}
	//招换技能，记录招换位置，需要传给Buff用
	pSkill->_posSummon = targetPos;
	m_pMaster->SetDir(dir);

	vector<Point3<float> > vPos;
	for (int i = 0; i < (int)vTmp.size(); ++i)
	{
		vTmp[i]->GetTargetMutPos(vPos);
	}
	BroadcastSkillUse broadcastskillInfo;
	broadcastskillInfo.set_skillid(skillId);
	for (uint32_t i = 0; i < targetCids.size(); i++)
		broadcastskillInfo.add_targetcids(targetCids[i]);
	broadcastskillInfo.set_usercid(m_pMaster->GetCid());
	ProtoBuf::Vector3PB *pPos = new ProtoBuf::Vector3PB();
	pPos->set_x(dir.x);
	pPos->set_y(dir.y);
	pPos->set_z(dir.z);
	broadcastskillInfo.set_allocated_dir(pPos);
	ProtoBuf::Vector3PB *pTargetPos = new ProtoBuf::Vector3PB();
	pTargetPos->set_x(targetPos.x);
	pTargetPos->set_y(targetPos.y);
	pTargetPos->set_z(targetPos.z);
	broadcastskillInfo.set_allocated_targetpos(pTargetPos);

	for (size_t i = 0; i < vPos.size();++i)
	{
		ProtoBuf::Vector3PB *pOtherTargetPos = broadcastskillInfo.add_muttargetpos();
		pOtherTargetPos->set_x(vPos[i].x);
		pOtherTargetPos->set_y(vPos[i].y);
		pOtherTargetPos->set_z(vPos[i].z);
		//broadcastskillInfo.setallo(pTargetPos);
	}

	m_pMaster->BroadCastData(EMODULE_ID_SKILL, LOGIC_TO_CLIENT_SKILL_USE_BROADCAST, (ProtoBufBase*)&broadcastskillInfo);

	//下发预警信息
	if (pSkill->_pSkillmeta->warn)
	{
		//一些无需目标技能，传目标点时，就传自身点，前端需求
		//下发预警消息
		SkillReadyRsp rsp;
		rsp.set_skillid(skillId);
		rsp.set_usercid(m_pMaster->GetCid());
		ProtoBuf::Vector3PB *pTargetPos = new ProtoBuf::Vector3PB();
		if (pSkill->_pSkillmeta->processTypes >	Range_none_target && pSkill->_pSkillmeta->processTypes <= Range_mine_in_rect)
		{
			pTargetPos->set_x(m_pMaster->GetPos().x);
			pTargetPos->set_y(m_pMaster->GetPos().y);
			pTargetPos->set_z(m_pMaster->GetPos().z);
		}
		else
		{
			pTargetPos->set_x(targetPos.x);
			pTargetPos->set_y(targetPos.y);
			pTargetPos->set_z(targetPos.z);
		}
		
		rsp.set_allocated_targetpos(pTargetPos);

		for (size_t i = 0; i < vPos.size(); ++i)
		{
			ProtoBuf::Vector3PB *pOtherTargetPos = broadcastskillInfo.add_muttargetpos();
			pOtherTargetPos->set_x(vPos[i].x);
			pOtherTargetPos->set_y(vPos[i].y);
			pOtherTargetPos->set_z(vPos[i].z);
			//broadcastskillInfo.setallo(pTargetPos);
		}

		m_pMaster->BroadCastData(LOGIC_TO_CLIENT_SKILL_READY, &rsp);
	}


	for (int i = 0; i < (int)vTmp.size(); ++i)
	{
		vTmp[i]->ReadyState(skillId);
	}


	//算消耗  AI使用的先屏蔽，后面AI里面加了判断再把这个加上
	//double value =GetValueFromFormula(skillId, (VEC_INT32 &)pSkill->_pSkillmeta->costValue,nullptr,0);
	//if (pSkill->_pSkillmeta->cost == Cost_mp)
	//{
	//	if ((double)m_pMaster->GetAttr(C_MP) < value)
	//	{
	//		return false;
	//	}
	//	m_pMaster->AddAttr(C_MP, -1 * (int64_t)value, true);
	//}
	//else if (pSkill->_pSkillmeta->cost == Cost_accpower)
	//{
	//	//m_pMaster->AddAttr(C_MP, -1 * value, true);
	//}

	//LogDebugFmtPrint("use skill skillid=%d", skillId);
	return true;
}


//物品使用技能,还是走技能流程，支持放指定位置的范围技
bool SkillPart::BeginUseSkillByItem(uint32_t skillId, uint32_t skillLev, Creature* pTarget)
{
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillId);
	if (!pConfig)
	{
		return false;
	}
	AddSkill(skillId, skillLev, 0, 0, false, false, enSkillSaveType_UseOnce);
	if (IsPassiveSkill(pConfig))
	{
		//被动技能，不用走下面了,在add skill里已处理了
		return true;
	}
	vecUint64_t targetCids;
	targetCids.push_back(m_pMaster->GetCid());
	BeginCreatureUseSkill(skillId,  targetCids,m_pMaster->GetDir(), m_pMaster->GetPos());

	return true;
}



bool SkillPart::BeginUseSkill(uint32_t skillId, vecUint64_t& targetCids, const Point3<float> &dir, const Point3<float>& targetPos)
{
	stSkillInfo* pSkill = GetSkillInfo(skillId);
	if (!pSkill)
		return false;
	if (!IsCanUseSkill(skillId, &targetCids))
		return false;
	Point3<float> tmpPos = targetPos;
	//判断和目标点是否有阻挡
	if (tmpPos.length()>0 && !m_pMaster->GetScene()->IsSkillEffectiveArea(m_pMaster->GetPos(), tmpPos))
	{
		LogDebugFmtPrint("can not use skill ,is EffectiveArea skillid=%d", skillId);
		return false;
	}

	pSkill->_cdTimeStamps = Time::Now().UnixMSec();

	std::vector<SkillBase * > vTmp;  //有可能一个技能，能产生多个战斗
	if (pSkill->_pSkillmeta->processTypes == process_bullet || pSkill->_pSkillmeta->processTypes==Process_SomeBullet)
	{
		if ((int)targetCids.size()<=0)
		{
			//子弹类型的技能，没有目标，直接退出
			LogDebugFmtPrint("bullet skill no target error");
			return false;
		}

		for (int i = 0; i < (int)targetCids.size(); ++i)
		{
			vector<uint64_t> vtargetList;
			vtargetList.push_back(targetCids[i]);
			//能使用，则生成战斗信息
			SkillBase * pSkillBase = FactoryCreateSkillFightInfo(skillId);
			if (!pSkillBase)
			{
				return false;
			}
			pSkillBase->SetSkillDir(dir);
			pSkillBase->SetTargetPos(targetPos);
			pSkillBase->SetTargetCidsList(vtargetList);
			vTmp.push_back(pSkillBase);
			
		}
	}
	else
	{
		SkillBase * pSkillBase = FactoryCreateSkillFightInfo(skillId);
		if (!pSkillBase)
		{
			return false;
		}

		pSkillBase->SetTargetPos(targetPos);
		pSkillBase->SetTargetCidsList(targetCids);
		pSkillBase->SetSkillDir(dir);
		vTmp.push_back(pSkillBase);
	}

	//if (pSkill->_pSkillmeta->processTypes == process_summon)
	//{
	//	vTmp.at(0)->SetSummonPos(targetPos);
	//}
	//招换物位置
	pSkill->_posSummon = targetPos;
	m_pMaster->SetDir(dir);

	BroadcastSkillUse broadcastskillInfo;
	broadcastskillInfo.set_skillid(skillId);
	for (uint32_t i = 0; i < targetCids.size(); i++)
		broadcastskillInfo.add_targetcids(targetCids[i]);
	broadcastskillInfo.set_usercid(m_pMaster->GetCid());
	ProtoBuf::Vector3PB *pPos = new ProtoBuf::Vector3PB();
	pPos->set_x(dir.x);
	pPos->set_y(dir.y);
	pPos->set_z(dir.z);
	broadcastskillInfo.set_allocated_dir(pPos);
	ProtoBuf::Vector3PB *pTargetPos = new ProtoBuf::Vector3PB();
	pTargetPos->set_x(targetPos.x);
	pTargetPos->set_y(targetPos.y);
	pTargetPos->set_z(targetPos.z);
	broadcastskillInfo.set_allocated_targetpos(pTargetPos);


	//判断是否转发这条释放技能消息，如果是自己专属怪，则不转发
	bool isBroad = true;
	Player * pPlayer = dynamic_cast<Player *>(m_pMaster);
	if (pPlayer)
	{
		for (int i = 0; i < (int)targetCids.size();++i)
		{
			if (pPlayer->IsOnlyOwnerMonster(targetCids[i]))
			{
				isBroad = false;
				break;
			}
		}
	}

	if (isBroad)
	{
		m_pMaster->BroadCastData(EMODULE_ID_SKILL, LOGIC_TO_CLIENT_SKILL_USE_BROADCAST, (ProtoBufBase*)&broadcastskillInfo);
	}
	
	//for (int i = 0; i < (int)vTmp.size();++i)
	//{
	//	vTmp[i]->ReadyState(skillId);
	//}

	//算消耗
	double value = GetValueFromFormula(skillId, (VEC_INT32&)pSkill->_pSkillmeta->costValue);
	if (pSkill->_pSkillmeta->cost == Cost_mp)
	{
		if ((double)m_pMaster->GetAttr(C_MP)<value)
		{
			return false;
		}
		m_pMaster->AddAttr(C_MP, -1 * (int64_t)value, true);
	}
	else if (pSkill->_pSkillmeta->cost == Cost_accpower)
	{
		//m_pMaster->AddAttr(C_MP, -1 * value, true);
	}
	

	////发送技能事件触发
	UseSkillEvent  useSkillEvent;
	useSkillEvent.skillid = skillId;
	//通知攻击者和受害者攻击事件
	g_GetEvent()->FireExecute(EVENT_USE_SKILL, m_pMaster->GetCid(), CREATURE_PLAYER, (UseSkillEvent*)&useSkillEvent, sizeof(UseSkillEvent));

	//拖放技能自动下马
	HorsePart* pHorsePart = dynamic_cast<HorsePart*>(m_pMaster->GetPart(PART_HORSE));
	if (pHorsePart)
	{
		pHorsePart->DismountHorse();
	}

	//解除无敌
	m_pMaster->SetBeAttackFlag(true);

	return true;
}


//判断技能消耗够不够
bool SkillPart::IsEnoughCost(uint32_t skillId)
{
	stSkillInfo* pSkill = GetSkillInfo(skillId);
	if (!pSkill)
		return false;
	//算消耗
	double value = GetValueFromFormula(skillId, (VEC_INT32 &)pSkill->_pSkillmeta->costValue, nullptr, 0);
	if (pSkill->_pSkillmeta->cost == Cost_mp)
	{
		if ((double)m_pMaster->GetAttr(C_MP) < value)
		{
			return false;
		}
	}

	return true;
}

//技能自身施放判断
bool SkillPart::IsCanUseSkill(uint32_t skillId, vecUint64_t* targetCids /* = nullptr */, uint32_t count, Creature * pSource)
{
	if (!pSource)
	{
		pSource = m_pMaster;
	}
	stSkillInfo* pSkill = GetSkillInfo(skillId);
	if (!pSkill || !pSkill->_pSkillmeta)
		return false;

	//该技能在冷却cd中
	int64_t leftCD = pSkill->GetLeftCDTime();
	if (leftCD > pSkill->_pSkillmeta->cd*0.2)  //只取5分之4的CD用于判断，以便服务器和客记端时间上有一点误差导致放不了技能
	{
		//LogDebugFmtPrint("skill in cd skillId:%d,current=%llu,lasttime=%llu,skillcd=%d", skillId, Time::Now().UnixMSec(), pSkill->_cdTimeStamps, pSkill->_pSkillmeta->cd);
		return false;
	}

	//判断自身有没有中不能施放技能的buff
	if (pSource->HasBuffStateNoSkill())
	{
		LogDebugFmtPrint("has noskill buff skillId:%d", skillId);
		return false;
	}

	//有些技能战斗状态不能释放
	if (pSkill->_pSkillmeta->processTypes == Process_Yingsheng)
	{
		Player * pPlayer = dynamic_cast<Player*>(pSource);
		if (pPlayer && pPlayer->IsFightState())
		{
			LogDebugFmtPrint("skill use failed because player is fightstate skillId:%d", skillId);
			return false;
		}
	}





	//******************技能消耗******************

	//uint32_t attrType = 0;
	//uint32_t value = 0;
	//if (Cost_none != pSkill->_pSkillmeta->cost)
	//{
	//	if (Cost_accpower == pSkill->pSkillmeta->cost)
	//	{
	//		value = 1;
	//		attrType = C_ACCPOWER;
	//	}
	//	else if (Cost_mp == pSkill->pSkillmeta->cost)
	//	{
	//		value = 1;
	//		attrType = C_MP;
	//	}

	//	if (m_pMaster->CheckAttrValue(attrType, value))
	//		m_pMaster->AddAttr(attrType, value, true);
	//	else
	//		return false;
	//}
	//

	//如果是有目标的技能，必须有目标
	if (pSkill->_pSkillmeta && pSkill->_pSkillmeta->rangeType < Range_none_target)
	{
		if (!targetCids)
		{
			LogErrFmtPrint("skill cant use, targets null, skillId:%d", skillId);
			return false;
		}
		//检查每个目标
		/*for (int32_t i = 0; i < pSkill->vTargetCids.size(); i++)
		{
		if (!IsCanBeAttackBySkill(pSkill->Id, (*targetCids)[i]))
		return false;
		}*/
		for (uint32_t i = 0; i < count; ++i)
		{
			if (!IsCanBeAttackBySkill(skillId, (*targetCids)[i], pSource))
			{
				return false;
			}
		}
	}

	//放技能时，有些是不能移动的
	if (!pSkill->_pSkillmeta->isMove)
	{
		MovePart * pPart = dynamic_cast<MovePart*>(m_pMaster->GetPart(PART_MOVE));
		if (pPart)
		{
			pPart->StopSelfMove();
		}

	}

	return true;
}

//敌我双方关系判断
bool SkillPart::IsCanBeAttackBySkill(uint32_t skillId, CharIDType targetCid, Creature * pSource)
{
	if (!pSource)
	{
		pSource = m_pMaster;
	}
	Creature *pCreature = g_GetSceneMgr()->GetCreature(pSource->GetSceneId(), targetCid);
	if (!pCreature)
		return false;

	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillId);
	if (!pConfig)
	{
		return false;
	}

	//if (pSkill->_pSkillmeta->type == FriendTarget)
	//{
	//	return true;
	//}
	//else
	{
		if (pConfig->type == enSkillTargetType_FriendBuffer || pConfig->type == enSKillTargetType_FriendDead || pConfig->type==enSkillTargetType_FriendBufferNotMyself)
		{
			if (pSource->IsFriendSide(pCreature))
			{
				if (pConfig->type == enSkillTargetType_FriendBufferNotMyself && pSource->GetCid()==pCreature->GetCid())
				{
					return false;
				}

				return true;
			}
			else
			{
				return false;
			}
			
		}
		else
		{
			if (pSource->GetCid() == targetCid)
			{
				return false;
			}

			if (pSource->IsFriendSide(pCreature))
			{
				return false;
			}
		}
	}
	
	return true;
}

//void SkillPart::ReadyState(uint32_t skillId)
//{
//	SkillBase* pSkill = GetSkillInfo(skillId);
//	if (!pSkill)
//		return;
//
//	//cd时间定时
//	uint32_t cdTimeId = cdTimeIdPre + skillId;
//	pSkill->cdTimeStamps = g_GetGlobalServerTime()->Tick() + pSkill->pSkillmeta->cd;
//	SetTimedo(cdTimeId, pSkill->pSkillmeta->cd, 1);
//
//	//LogDebugFmtPrint("skill readytime begin, skillId:%d", skillId);
//	if (pSkill->pSkillmeta->readyTime <= 0)
//	{
//		DamageState(skillId);
//		return;
//	}
//	pSkill->curState = SkillState_ready;
//	SetTimedo(skillId, pSkill->pSkillmeta->readyTime, 1);
//
//	/*
//	if (pSkill->pSkillmeta->breakTime == BreakTime_ready ||
//		pSkill->pSkillmeta->breakTime == BreakTime_All)
//	{
//
//	}
//	*/
//}
//
//void SkillPart::DamageState(uint32_t skillId)
//{
//	SkillBase* pSkill = GetSkillInfo(skillId);
//	if (!pSkill)
//		return;
//	KillTimedo(skillId);
//	pSkill->curState = SkillState_damage;
//
//	//LogDebugFmtPrint("skill ready timeover, damagetime begin, damgeCount:%d, skillId:%d",pSkill->pSkillmeta->damageTime.size(), skillId);
//	if (pSkill->pSkillmeta->damageTime.empty())
//		OnDamageTimedo(skillId);
//	else
//	{
//		if (pSkill->pSkillmeta->processTypes == process_bullet)
//		{
//			if (pSkill->vTargetCids.size() > 1)
//			{
//				if (pSkill->pSkillmeta->damageTime.size() > 1)
//					SetTimedo(skillId, pSkill->pSkillmeta->damageTime[0], 1);
//				else
//				{
//					//单个子弹单个目标对象
//					BulletProcess(skillId);
//					pSkill->refreshData();
//				}
//			}
//			else
//			{
//				//多个子弹多个目标 1对1作用
//				for (uint32_t i = 0; i < pSkill->pSkillmeta->damageTime.size(); i++)
//					BulletProcess(skillId, i);
//				pSkill->refreshData();
//			}
//		}
//		else
//			SetTimedo(skillId, pSkill->pSkillmeta->damageTime[0], 1);
//
//		//订阅打断事件
//	}
//}
//
//void SkillPart::OnDamageTimedo(uint32_t skillId)
//{
//	SkillBase *pSkill = GetSkillInfo(skillId);
//	if (!pSkill)
//		return;
//
//	KillTimedo(skillId);
//
//	uint32_t targetCid = 0;
//
//	//根据时间点来取找当前目标
//	if (Range_none_target > pSkill->pSkillmeta->rangeType)
//	{
//		//uint32_t targetcount = pSkill->vTargetCids.size();
//		//uint32_t i = targetcount - 1;
//		//if (targetcount <= pSkill->curDamageCount)
//		//	i = targetcount - 1;
//		//else
//		//	i = pSkill->curDamageCount;
//
//		//if (i >= 0 && i < pSkill->vTargetCids.size())
//		//	targetCid = pSkill->vTargetCids[i];
//		if (pSkill->curDamageCount >= pSkill->vTargetCids.size() )
//		{
//			LogDebugFmtPrint("SkillPart::OnDamageTimedo curDamagercount=%d,pSkill->vTargetCids.size()=%d", pSkill->curDamageCount, (int)pSkill->vTargetCids.size());
//			return;
//		}
//
//
//		targetCid = pSkill->vTargetCids[pSkill->curDamageCount];
//	}
//
//	//LogDebugFmtPrint("skill damagetimeDo, curdamgeCount:%d, skillId:%d, targetCid:%d", pSkill->curDamageCount, skillId, targetCid);
//	FindCreatures(pSkill->pSkillmeta, targetCid, pSkill->targetPos, pSkill->curDamageCount, pSkill->focoTime);
//
//	if (pSkill->pSkillmeta->damageTime.size() > pSkill->curDamageCount+1 )
//	{
//		pSkill->curDamageCount++;
//		SetTimedo(skillId, pSkill->pSkillmeta->damageTime[pSkill->curDamageCount], 1);
//	}
//	else
//	{
//		//LogDebugFmtPrint("skill damge done, skillId:%d", skillId);
//		pSkill->refreshData();
//	}
//}
//
//void SkillPart::OnReadyTimedo(uint32_t skillId)
//{
//	DamageState(skillId);
//}
Creature * SkillPart::GetCreature(CharIDType createCid)
{
	Scene *pScene = m_pMaster->GetScene();
	if (!pScene)
		return nullptr;

	return pScene->GetCreature(createCid);
}

Point3<float>  SkillPart::GetMasterPos()
{
	return m_pMaster->GetPos();
}
Point3<float>  SkillPart::GetMasterDir()
{
	return m_pMaster->GetDir();
}

CharIDType SkillPart::GetMasterCid()
{
	return m_pMaster->GetCid();
}

Creature * SkillPart::GetMaster()
{
	return m_pMaster;
}




void  SkillPart::FindCreatures(const SkillCfg* pSkillmeta, Point3<float> masterPos,Point3<float> skillDir, CharIDType targetCid, Point3<float> targetpos, uint32_t damagePoint, uint32_t focotime, cList &tmpList)
{
	//std::list<uint32_t> clist;
	Scene *pScene = m_pMaster->GetScene();
	if (!pScene)
		return;

	Point3<float> finalpos, dir;
	vector<double> args;
	Point3<float> skillActivePos=m_pMaster->GetPos(); //技能生效点，用于阻挡
	//int32_t cArg;
//	uint32_t userId = m_pMaster->GetCid();
	Creature *pTarget = nullptr;
//	uint32_t lev = GetSkillLev(pSkillmeta->skillID);

	VEC_INT32 tmpParam;
	VEC_FLOAT tmpFloatParam;
	for (size_t i = 0; i < pSkillmeta->funcRangeTypeValue.size(); i++)
	{
		//m_pMaster->GetFormula(pSkillmeta->funcRangeTypeValue[i].c_str(), tmpParam);
		//cArg = m_pMaster->DoSkillString(pSkillmeta->skillID, lev, pSkillmeta->funcRangeTypeValue[i].c_str(), userId, targetCid, focotime);
		//args.push_back((float)cArg/1000);
		tmpFloatParam.clear();
		for (int j = 0; j < (int)pSkillmeta->funcRangeTypeValue[i].size(); ++j)
		{
			tmpFloatParam.push_back(pSkillmeta->funcRangeTypeValue[i][j] / 1000.0);
		}

		//如果大于三个参数，表示是公式
		if ((int)args.size()>=3)
		{
			double value = GetValueFromFormula(pSkillmeta->skillID, tmpParam, m_pMaster);
			args.push_back(value);
		}
		else
		{
			for (int j = 0; j < (int)tmpFloatParam.size(); ++j)
			{
				args.push_back(tmpFloatParam[j]);
			}
		}
	}

	
	


	switch (pSkillmeta->rangeType)
	{
	case Range_target:
		tmpList.push_back(targetCid);
		break;
	case Range_mine:
		tmpList.push_back(m_pMaster->GetCid());
		break;
//******************矩形范围******************
	case Range_mine_rect_side:
	case Range_mine_rect_side_copy:
		if (args.size() < 2)
		{
			LogErrFmtPrint("Range_mine_rect_side or copy  args error, skillId:%d, argSize:%d", pSkillmeta->skillID, args.size());
			return;
		}
		//先找以自己为圆心，模型半径为半径的圆，主要是为了处理有怪物和自己基本重叠，但是坐标在玩家后面打不到的问题
		if (point2LengthSquare(masterPos ,m_pMaster->GetPos())<=0.01)
		{
			pScene->FindCreatureInCircle(tmpList, m_pMaster->GetPos(), m_pMaster->GetModelRadius());
		}
		
		pScene->FindCreatureInRect(tmpList, masterPos, skillDir, args[0], args[1], 0);
		break;
	case Range_target_rect_side:
		pTarget = pScene->GetCreature(targetCid);
		if (!pTarget) 
		{
			LogDebugFmtPrint("target is out of scence, targetId:%d, myId:%d, skillId:%d", targetCid, m_pMaster->GetCid(), pSkillmeta->skillID);
			return;
		}
		if (args.size() < 2)
		{
			LogErrFmtPrint("args error, skillId:%d, argSize:%d", pSkillmeta->skillID, args.size());
			return;
		}
		pScene->FindCreatureInRect(tmpList, pTarget->GetPos(), skillDir, args[0], args[1], 0);
		skillActivePos = pTarget->GetPos();
		break;
	case Range_mine_in_rect:
		if (args.size() < 2)
		{
			LogErrFmtPrint("Range_mine_in_rect args error, skillId:%d, argsSize=%d", pSkillmeta->skillID, args.size());
			return;
		}
		pScene->FindCreatureInRect(tmpList, m_pMaster->GetPos(), m_pMaster->GetDir(),m_pMaster->GetPos(),args[0], args[1], 0);
		break;
	case Range_pos_rect_target:
	{
		if (args.size() < 2)
		{
			 LogErrFmtPrint("Range_mine_in_rect args error, skillId:%d, argsSize=%d", pSkillmeta->skillID, args.size());
			 return;
		}
		pScene->FindCreatureInRect(tmpList, targetpos, m_pMaster->GetDir(), targetpos, args[0], args[1], 0);
		skillActivePos = targetpos;
	}
		break;
//******************圆形******************
	case Range_pos_circle:
	case Range_pos_circle_target:
		if (args.empty())
		{
			LogErrFmtPrint("Range_mine_circle args error, skillId:%d, argsSize=%d", pSkillmeta->skillID, args.size());
			return;
		}
		pScene->FindCreatureInCircle(tmpList, targetpos, args[0], 0);
		skillActivePos = targetpos;
		break;
	case Range_mine_circle:
	{
		if (args.empty())
		{
			 LogErrFmtPrint("Range_mine_circle args error, skillId:%d, argsSize=%d", pSkillmeta->skillID, args.size());
			 return;
		 }
		pScene->FindCreatureInCircle(tmpList, m_pMaster->GetPos(), args[0], 0);
		 break;
	}
	case Range_mine_circle_copy:
		if (args.empty())
		{
			LogErrFmtPrint("Range_mine_circle args error, skillId:%d, argsSize=%d", pSkillmeta->skillID, args.size());
			return;
		}

		if (m_pMaster->CreatureKind()!=CREATURE_PLAYER)
		{
			pScene->FindCreatureInCircle(tmpList, m_pMaster->GetPos(), args[0], 0);
		}
		else
		{
			//玩家的有些有位移有技能要特殊处理。
			if (pSkillmeta->releaseType == 3 || targetpos.length() == 0)  //可以移动施法的
			{
				pScene->FindCreatureInCircle(tmpList, m_pMaster->GetPos(), args[0], 0);
			}
			else //对于一些有位移的，没有目标的技能，以客户端发来的点为准
			{
				pScene->FindCreatureInCircle(tmpList, targetpos, args[0], 0);
				skillActivePos = targetpos;
			}
		}

		
		break;
	case Range_target_circle:
		pTarget = pScene->GetCreature(targetCid);
		if (!pTarget) 
		{
			LogDebugFmtPrint("target is out of scence, targetId:%d, myId:%d, skillId:%d", targetCid, m_pMaster->GetCid(), pSkillmeta->skillID);
			return;
		}
	
		if (args.empty())
		{
			LogErrFmtPrint("Range_target_circle error, skillId:%d, argsSize=%d", pSkillmeta->skillID, args.size());
			return;
		}
		pScene->FindCreatureInCircle(tmpList, pTarget->GetPos(), args[0], 0);
		skillActivePos = pTarget->GetPos();
		break;
	case Range_Some_Pos:
	{
		if ((int)args.size()%3!=0)
		{
			LogDebugFmtPrint("skillid=%d funcRangeTypeValue parama error mod 3 !=0 ", pSkillmeta->skillID);
			return;
		}
		for (int i = 0; i < (int)args.size(); i = i + 3)
		{
			if (pSkillmeta->processTypes == Process_SomePointDelayAoe && i!=(int)damagePoint)
			{
				continue;
			}
			cList tmpRangeList;

			float range = args[i];
			float distance = args[i + 1];
			float radius = args[i + 2];

			// x1 = x0 * cosB + y0 * sinB
			// y1 = -x0 * sinB + y0 * cosB
			Point3<float> tmpDir;
			tmpDir.x = m_pMaster->GetDir().x*cos(AngleToRadian(range)) + m_pMaster->GetDir().z*sin( AngleToRadian(range));
			tmpDir.z = -1 * m_pMaster->GetDir().x * sin(AngleToRadian(range)) + m_pMaster->GetDir().z*cos( AngleToRadian(range));
			tmpDir.y = 0;

			Point3<float> tmpPos = m_pMaster->GetPos() + distance*tmpDir;

			pScene->FindCreatureInCircle(tmpRangeList, tmpPos, radius, 0);
			tmpList.insert(tmpList.end(), tmpRangeList.begin(), tmpRangeList.end());

			LogDebugFmtPrint("pos(%f,%f,%f),tmpRangeList.size()=%d",tmpPos.x,tmpPos.y,tmpPos.z,tmpRangeList.size());
		}
						   
	}
	break;
//******************扇形范围******************
	case Range_mine_sector:
	case Range_mine_sector_copy:
		if (args.size() < 2)
		{
			LogErrFmtPrint("Range_mine_sector or copy  args error, skillId:%d, argSize:%d", pSkillmeta->skillID, args.size());
			return;
		}
		//先找以自己为圆心，模型半径为半径的圆，主要是为了处理有怪物和自己基本重叠，但是坐标在玩家后面打不到的问题
		if (point2LengthSquare(masterPos, m_pMaster->GetPos()) <= 0.01)
		{
			pScene->FindCreatureInCircle(tmpList, m_pMaster->GetPos(), m_pMaster->GetModelRadius());
		}
		pScene->FindCreatureInSector(tmpList, m_pMaster->GetPos(), m_pMaster->GetDir(), args[1], args[0], 0);
		break;
	case Range_Some_Random_pos: 
	{
		//这里是找怪物攻击范围的所有玩家，真正的随要放技能本身处理了
		pScene->FindCreatureInCircle(tmpList, targetpos, args[0], 0);
	}
	break;
	case Range_none:
	{
		if (targetCid>0)
		{
			tmpList.push_back(targetCid);
		}
		else
		{
			//如果是没有范围类型，则默认为对于自身的技能
			tmpList.push_back(m_pMaster->GetCid());
		}
	}
	break;
	default:
		LogDebugFmtPrint("empty skill cid:%llu, skillId:%d", m_pMaster->GetCid(), pSkillmeta->skillID);
		break;
	}

	//判断目标和技能点有没阻挡
	//有些技能是指定目标类型的
	//有些位面中的怪和专属怪是不能被其它人伤害到的.
	cList::iterator iter = tmpList.begin();
	for (; iter != tmpList.end();)
	{
		Creature * pCreate = GetCreature(*iter);
		if (!pCreate)
		{
			iter = tmpList.erase(iter);
			continue;
		}

		if (m_pMaster->ViewFliter(pCreate, 1)) //位面中，或看不见的玩家，不受技能影响
		{
			iter = tmpList.erase(iter);
			continue;
		}

		if ((pCreate->GetCanBeSeenFlag()==false || (!m_pMaster->GetScene()->IsSkillEffectiveArea(skillActivePos, pCreate->GetPos())) ||
			(pCreate->CreatureKind() != CREATURE_PLAYER &&
			pCreate->CreatureKind() != CREATURE_MONSTER &&
			pCreate->CreatureKind() != CREATURE_NPC)))
		{
			iter = tmpList.erase(iter);
		}
		else
		{
			//再判断有没有要判断技能目标筛选的,目前填了这个的，只找怪物
			if ((int)pSkillmeta->vTargetType.size() > 0)
			{
				if (pCreate->CreatureKind() == CREATURE_MONSTER)
				{
					Monster * pMonster = dynamic_cast<Monster *>(pCreate);
					if (pMonster)
					{
						bool bFind = false;
						for (int i = 0; i < (int)pSkillmeta->vTargetType.size(); ++i) //只留下指定类型的怪物
						{
							if ((int32_t)pMonster->GetParentMonsterType() == pSkillmeta->vTargetType[i])
							{
								bFind = true;
								break;
							}
						}
						if (bFind)
						{
							++iter;
						}
						else
							iter = tmpList.erase(iter);
					}
				}
				else
				{
					iter = tmpList.erase(iter);
				}
				
			}
			else
			{
				iter++;
			}

		}
	}

	

	return;
}

//技能结果
void  SkillPart::SkillResult(uint32_t skillid, const SkillCfg* pSkillmeta, uint32_t damagePoint, uint32_t focotime, cList & tmpList)
{
	//BEGIN_PROFILE("SkillBase::SkillResult");

	if (m_pMaster->IsDead() && pSkillmeta->deadBreak==1)
	{
		//是死亡中断技能，直接不算结果
		return;
	}


	UseSkillResult useResult;
	useResult.set_skillid(skillid);

	useResult.set_usercid(m_pMaster->GetCid());

	uint32_t lev = GetSkillLev(pSkillmeta->skillID);

	Creature * pSource = m_pMaster;

	int32_t calcNum = 0;
	bool abandon = true;
	cList::iterator iter = tmpList.begin();
	for (; iter != tmpList.end();)
	{
		if (IsCanBeAttackBySkill(skillid, *iter, pSource))
		{
			Calculate(pSource,useResult, pSkillmeta, *iter, damagePoint, focotime, abandon);
			abandon = false;
			calcNum++;
			if (pSkillmeta->goalMaxNum>0 && calcNum >= pSkillmeta->goalMaxNum)  //达到人数，则直接跳出
			{
				break;
			}
			iter++;
		}
		else
		{
			iter=tmpList.erase(iter);
		}
	}

	//这里主要针对一些敌方技能，但是带有状态包，是给自己的，在没有打中敌方的情况下，也要给自己加上buff的情况
	if (tmpList.size() <= 0 )  
	{
		if (pSkillmeta->damageType != Damage_none)
		{
			if (StateBagWithDamagePoint(pSource, pSkillmeta, lev, useResult, m_pMaster, damagePoint, abandon))
			{
				abandon = false;
				////攻击事件触发
				//skillAttackEvent  attackInfo;
				//attackInfo.skillId = pSkillmeta->skillID;
				//attackInfo.victim = 0;
				//attackInfo.attacker = m_pMaster->GetCid();
				//attackInfo.sufferedValue = 0;

				////通知攻击者和受害者攻击事件
				//g_GetEvent()->FireExecute(EVENT_ATTACK_SOMEBODY, m_pMaster->GetCid(), 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));
			}
		}
		else
		{
			if (StateBagAll(pSource,pSkillmeta, lev, useResult, m_pMaster, abandon))
			{
				abandon = false;
				////攻击事件触发
				//skillAttackEvent  attackInfo;
				//attackInfo.skillId = pSkillmeta->skillID;
				//attackInfo.victim = 0;
				//attackInfo.attacker = m_pMaster->GetCid();
				//attackInfo.sufferedValue = 0;

				////通知攻击者和受害者攻击事件
				//g_GetEvent()->FireExecute(EVENT_ATTACK_SOMEBODY, m_pMaster->GetCid(), 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));
			}
		}
	}

	if (!abandon)
	{
		
		//if (pSkillmeta->processTypes == Process_Yingsheng)
		//{
		//	//攻击事件触发
		//	skillAttackEvent  attackInfo;
		//	attackInfo.skillId = pSkillmeta->skillID;
		//	attackInfo.victim = 0;
		//	attackInfo.attacker = m_pMaster->GetCid();
		//	attackInfo.sufferedValue = 0;
		//	g_GetEvent()->FireExecute(EVENT_USE_SKILL_ATTACK, m_pMaster->GetCid(), 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));
		//}

		pSource->BroadCastData(EMODULE_ID_SKILL, LOGIC_TO_CLIENT_SKILL_RESULT_BROADCAST, (ProtoBufBase*)&useResult, true);

		//LogDebugFmtPrint("broad skillresult skillid=%d",skillid);


			//发送完消息后，统一扣血，替死buff有需求
			mapSkillDamage::iterator iter = m_mapSkillResultDamage.begin();
			for (; iter != m_mapSkillResultDamage.end(); ++iter)
			{
				Creature * pCreature = g_GetCreatureMgr()->GetCreature(iter->first);
				if (pCreature)
				{
					pCreature->AddAttr(C_HP, -1 * (int64_t)iter->second, false, m_pMaster->GetCid());
				}
			}

		m_mapSkillResultDamage.clear();
	}
	//END_PROFILE();
}


//分担技能结果,只算一个伤害，分担给其它人
void SkillPart::SkillResultShareDamage(uint32_t skillid, const SkillCfg* pSkillmeta, CharIDType targetID, cList & tmpList)
{
	UseSkillResult useResult;
	//uint32_t lev = GetSkillLev(pSkillmeta->skillID);
	Creature * pSource = m_pMaster;
	//if (m_pMaster->CreatureKind() == CREATURE_PET)
	//{
	//	CPet * pPet = dynamic_cast<CPet*>(m_pMaster);
	//	if (pPet)
	//	{
	//		pSource = pPet->GetMaster();
	//	}
	//}

	Calculate(pSource, useResult, pSkillmeta, targetID, 0, 0,true);
	if (useResult.targets_size() > 0)
	{
		//攻击事件触发
		skillAttackEvent  attackInfo;
		attackInfo.skillId = pSkillmeta->skillID;
		attackInfo.victim = 0;
		attackInfo.attacker = m_pMaster->GetCid();
		attackInfo.sufferedValue = 0;
		g_GetEvent()->FireExecute(EVENT_USE_SKILL_ATTACK, m_pMaster->GetCid(), 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));
	}

	if (tmpList.size()<=0)
	{
		LogDebugFmtPrint("skillid=%d is not find target error", skillid);
		return;
	}

	//修改目标所受伤害值
	uint32_t damageAvg = m_mapSkillResultDamage[targetID] / (uint32_t)tmpList.size();
	useResult.Clear(); //不想再将上面接口再改一次，所以这里就直接把这个结构先清下，再赋值

	useResult.set_skillid(skillid);
	useResult.set_usercid(m_pMaster->GetCid());
	//重新修改伤害值
	cList::iterator iter = tmpList.begin();
	for (; iter != tmpList.end(); iter++)
	{
		Creature * pTarget = g_GetCreatureMgr()->GetCreature(*iter);
		if (!pTarget)
		{
			continue;
		}

		UseSkillResult::Target *pClientTarget = useResult.add_targets();
		pClientTarget->set_targetcid(*iter);

		pClientTarget->set_bedead(pTarget->IsDead());
		Attr *pAttr = pClientTarget->add_creatureattr();
		pAttr->set_attrnum(pTarget->GetAttrNum(C_HP));

		if (pTarget->GetAttr(C_HP) - damageAvg < 0)
		{
			pAttr->set_attrvalue(0);
		}
		else
		{
			pAttr->set_attrvalue(pTarget->GetAttr(C_HP) - damageAvg);
		}

		DigPerfor* pdigti = pClientTarget->add_digperfors();
		pdigti->set_value(damageAvg);
		pdigti->set_type(DigPerfor_Type_reduceHp);


		//发送受击事件
		if (*iter!=targetID)
		{
			//攻击事件触发
			skillAttackEvent  attackInfo;
			attackInfo.skillId = pSkillmeta->skillID;
			attackInfo.victim = *iter;
			attackInfo.attacker = m_pMaster->GetCid();
			attackInfo.sufferedValue = damageAvg;

			//BEGIN_PROFILE("SkillPart::FireExecute");
			//通知攻击者和受害者攻击事件
			g_GetEvent()->FireExecute(EVENT_ATTACK_SOMEBODY, m_pMaster->GetCid(), 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));
			g_GetEvent()->FireExecute(EVENT_UNDER_ATTACK, *iter, 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));

			//END_PROFILE();

			//BEGIN_PROFILE("SkillPart::AddAttr");
			
		}

		m_mapSkillResultDamage[*iter] = damageAvg;
	}

	pSource->BroadCastData(EMODULE_ID_SKILL, LOGIC_TO_CLIENT_SKILL_RESULT_BROADCAST, (ProtoBufBase*)&useResult, true);

	//LogDebugFmtPrint("broad skillresult skillid=%d",skillid);

	//发送完消息后，统一扣血，替死buff有需求
	mapSkillDamage::iterator iterResult = m_mapSkillResultDamage.begin();
	for (; iterResult != m_mapSkillResultDamage.end(); ++iterResult)
	{
		Creature * pCreature = g_GetCreatureMgr()->GetCreature(iterResult->first);
		if (pCreature)
		{
			pCreature->AddAttr(C_HP, -1 * (int64_t)iterResult->second, false, m_pMaster->GetCid());
		}
	}

	m_mapSkillResultDamage.clear();
	
}


//技能结果
//void  SkillPart::SkillFlyResult(uint32_t skillid, const SkillCfg* pSkillmeta, uint32_t damagePoint, uint32_t focotime, cList targetList)
//{
//	UseSkillResult useResult;
//	useResult.set_skillid(skillid);
//	useResult.set_usercid(m_pMaster->GetCid());
//
//	bool abandon = true;
//	cList::iterator iter = targetList.begin();
//	for (; iter != targetList.end(); iter++)
//	{
//		if (IsCanBeAttackBySkill(skillid, *iter))
//		{
//			Calculate(useResult, pSkillmeta, *iter, damagePoint, focotime);
//			abandon = false;
//		}
//	}
//
//	if (!abandon)
//		m_pMaster->BroadCastData(EMODULE_ID_SKILL, LOGIC_TO_CLIENT_SKILL_RESULT_BROADCAST, (ProtoBufBase*)&useResult, true);
//}

//无目标对像的，只需要发送状态包的技能结果,这个目标会默认为自己
void SkillPart::SkillNoTageteResult(uint32_t skillid, const SkillCfg* pSkillmeta, uint32_t damagePoint, uint32_t focotime)
{
	UseSkillResult useResult;
	useResult.set_skillid(skillid);
	useResult.set_usercid(m_pMaster->GetCid());

	Calculate(m_pMaster,useResult, pSkillmeta, m_pMaster->GetCid(), damagePoint, focotime,false);

	m_pMaster->BroadCastData(EMODULE_ID_SKILL, LOGIC_TO_CLIENT_SKILL_RESULT_BROADCAST, (ProtoBufBase*)&useResult, true);
}



  //同场景内传送
bool SkillPart::Teleporting(Point3<float>& dstPos)
{
	Player * pPlayer = dynamic_cast<Player*> (m_pMaster);
	if (pPlayer)
	{
		MovePart* pPart = dynamic_cast<MovePart*>(pPlayer->GetPart(PART_MOVE));
		if (pPart)
		{
			pPart->Teleporting(dstPos);
		}
	}

	return true;
}

//计算特殊怪物受伤害,为0表示不是特殊怪
uint32_t SkillPart::CalulateSpeciaMonsterDamage(UseSkillResult& useResult, const SkillCfg* pSkillmeta, CharIDType targetCid)
{
	uint32_t damage = 0;
	Creature *ptarget = g_GetSceneMgr()->GetCreature(m_pMaster->GetSceneId(), targetCid);
	if (ptarget && ptarget->CreatureKind() == CREATURE_MONSTER)
	{
		Monster * pMonster = dynamic_cast<Monster*>(ptarget);
		if (pMonster)
		{
			if (pMonster->GetParentMonsterType() == PARENT_MONSTER_TYPE_CAN_DESTROYED_THING || pMonster->GetMonsterInfo()->isOneHpHurt)
			{
				damage = 1;

				UseSkillResult::Target *pClientTarget = useResult.add_targets();
				pClientTarget->set_targetcid(targetCid);

				pClientTarget->set_bedead(ptarget->IsDead());
				Attr *pAttr = pClientTarget->add_creatureattr();
				pAttr->set_attrnum(ptarget->GetAttrNum(C_HP));

				if (ptarget->GetAttr(C_HP) - damage < 0)
				{
					pAttr->set_attrvalue(0);
				}
				else
				{
					pAttr->set_attrvalue(ptarget->GetAttr(C_HP) - damage);
				}


				DigPerfor* pdigti = pClientTarget->add_digperfors();
				pdigti->set_value(damage);
				pdigti->set_type(DigPerfor_Type_reduceHp);
				

				//攻击事件触发
				skillAttackEvent  attackInfo;
				attackInfo.skillId = pSkillmeta->skillID;
				attackInfo.victim = targetCid;
				attackInfo.attacker = m_pMaster->GetCid();
				attackInfo.sufferedValue = 1;


				//通知攻击者和受害者攻击事件
				g_GetEvent()->FireExecute(EVENT_ATTACK_SOMEBODY, m_pMaster->GetCid(), 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));
				g_GetEvent()->FireExecute(EVENT_UNDER_ATTACK, targetCid, 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));

				//放这里扣血，主要是让返击事件先触发，有些计算在受击事件里面，注意这里的先后顺序
				ptarget->AddAttr(C_HP, -1 * (int64_t)damage, false, m_pMaster->GetCid());


				LogDebugFmtPrint("skill use target is special monster reduce one hp monsterid=%d", ptarget->GetConfigId());

				return damage;
			}

		}
	}

	return damage;
}

void SkillPart::Calculate(Creature *pSource,UseSkillResult& useResult, const SkillCfg* pSkillmeta, CharIDType targetCid, uint32_t damagePoint, uint32_t focoTime, bool isNeedCalculateMyself)
{

	//BEGIN_PROFILE("SkillPart::Calculate");
	Creature *ptarget = g_GetSceneMgr()->GetCreature(pSource->GetSceneId(), targetCid);
	if (!ptarget || ptarget->IsDead())
		return;

	//判断是否是特殊怪物，不走正常的技能流程
	if (CalulateSpeciaMonsterDamage(useResult,pSkillmeta,targetCid)>0)
	{
		return;
	}
	uint32_t lev = GetSkillLev(pSkillmeta->skillID);
	uint32_t damage = 0;
	UseSkillResult::Target *pskillClientTarget = useResult.add_targets();
	pskillClientTarget->set_targetcid(targetCid);

	if (pSkillmeta->damageType != Damage_none)
	{
		//BEGIN_PROFILE("SkillPart::CalculateHit");
		//END_PROFILE();
		
		switch (pSkillmeta->damageType)
		{
		case Damage_pa:
		{
			if (false == CalculateHitAp(pSource,pskillClientTarget, ptarget, pSkillmeta, focoTime))
				return;

			//BEGIN_PROFILE("SkillPart::CalculateAp");
			damage = CalculateAp(pSource,pskillClientTarget, ptarget, pSkillmeta, damagePoint, focoTime);
						 // END_PROFILE();
		}
			break;
		case Damage_mat:
		{
			if (false == CalculateHitMat(pSource,pskillClientTarget, ptarget, pSkillmeta, focoTime))
				return;
		//   BEGIN_PROFILE("SkillPart::CalculateMat");
			damage = CalculateMat(pSource,pskillClientTarget, ptarget, pSkillmeta, damagePoint, focoTime);
						 //  END_PROFILE();
		}
			break;
		case Damage_heal:
		{
							//BEGIN_PROFILE("SkillPart::CalculateMat");
							//CalculateHeal(pskillClientTarget, ptarget, pSkillmeta, damagePoint, focoTime);
							//END_PROFILE();
		}
			break;
		case Damage_Prof:
		{
			if (m_pMaster->CreatureKind() != CREATURE_PLAYER && m_pMaster->CreatureKind() != CREATURE_PET)
				break;

			int64_t prof = pSource->GetAttr(C_PROF);
			if (prof == ECHARACTER_PROF_MAGICIAN)
			{
				if (false == CalculateHitMat(pSource,pskillClientTarget, ptarget, pSkillmeta, focoTime))
					return;
				damage = CalculateMat(pSource,pskillClientTarget, ptarget, pSkillmeta, damagePoint, focoTime);
			}
				
			else
			{
				if (false == CalculateHitAp(pSource,pskillClientTarget, ptarget, pSkillmeta, focoTime))
					return;
				damage = CalculateAp(pSource,pskillClientTarget, ptarget, pSkillmeta, damagePoint, focoTime);
			}	
		}
			
			break;
		default:
			LogErrFmtPrint("skill damage type error, skillId:%d, type:%d", pSkillmeta->skillID, pSkillmeta->damageType);
			break;
		}

		StateBagWithDamagePoint(pSource,pSkillmeta, lev, useResult, ptarget, damagePoint, isNeedCalculateMyself);

		//END_PROFILE();

		//BEGIN_PROFILE("SkillPart::AddAttr");
		m_mapSkillResultDamage[ptarget->GetCid()] = damage;
		//END_PROFILE();

	}
	else
	{
		StateBagAll(pSource,pSkillmeta, lev, useResult, ptarget, isNeedCalculateMyself);

		////攻击事件触发
		//skillAttackEvent  attackInfo;
		//attackInfo.skillId = pSkillmeta->skillID;
		//attackInfo.victim = 0;
		//attackInfo.attacker = m_pMaster->GetCid();
		//attackInfo.sufferedValue = 0;

		////通知攻击者和受害者攻击事件
		//g_GetEvent()->FireExecute(EVENT_ATTACK_SOMEBODY, m_pMaster->GetCid(), 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));

		//LogDebugFmtPrint("only buff skill, Id:%d", pSkillmeta->skillID);
	}


	//祝福类技能,隐身，不算攻击
	if ((pSkillmeta->processTypes == Process_Yingsheng) ||
		(pSkillmeta->type != enSkillTargetType_FriendBuffer &&
		pSkillmeta->type != enSKillTargetType_FriendDead &&
		pSkillmeta->type != enSkillTargetType_FriendBufferNotMyself ) )
	{
		//攻击事件触发
		skillAttackEvent  attackInfo;
		attackInfo.skillId = pSkillmeta->skillID;
		attackInfo.victim = targetCid;
		attackInfo.attacker = m_pMaster->GetCid();
		attackInfo.sufferedValue = damage;

		//BEGIN_PROFILE("SkillPart::FireExecute");
		//通知攻击者和受害者攻击事件
		g_GetEvent()->FireExecute(EVENT_ATTACK_SOMEBODY, m_pMaster->GetCid(), 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));
		g_GetEvent()->FireExecute(EVENT_UNDER_ATTACK, targetCid, 0, (skillAttackEvent*)&attackInfo, sizeof(skillAttackEvent));
	}



	//END_PROFILE();
}

uint32_t SkillPart::CalculateAp(Creature *pSource,UseSkillResult::Target *pClientTarget, Creature *pTarget, const SkillCfg* pskillmeta, uint32_t damagePoint, uint32_t focoTime)
{
	//伤害计算
	int32_t damage = 0;
	//uint32_t userId = m_pMaster->GetCid();
	//uint32_t targetId = m_pMaster->GetCid();
	uint32_t skillId = pskillmeta->skillID;
	
	int32_t skillDamageAdjust = GetSkillAttackPercent(skillId, damagePoint,pTarget);// FuncLua(skillId, pskillmeta->funcDamageRate, damagePoint, userId, targetId, focoTime);
	//技能固定伤害值
	int32_t skillDamgefix = GetSkillHurtFix(skillId,damagePoint,pTarget);// FuncLua(skillId, pskillmeta->funcDamageValue, damagePoint, userId, targetId, focoTime);
	int32_t skillAttackAdjust = GetSkillHurtPercent(skillId,damagePoint,pTarget);// FuncLua(skillId, pskillmeta->funcAttackRate, damagePoint, userId, targetId, focoTime);
	//技能附加固定
	int32_t skillAttackfix = GetSkillAttackfix(skillId, damagePoint,pTarget); //FuncLua(skillId, pskillmeta->funcAttackValue, damagePoint, userId, targetId, focoTime);

	pSource->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(m_pMaster->CreatureKind(), C_AP), skillAttackfix);
	pSource->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(m_pMaster->CreatureKind(),C_APRATE), skillAttackAdjust, true);

	int32_t cAp = pSource->GetAttr(C_AP);
	int32_t cDp = pTarget->GetAttr(C_DP); 

	//float damageAdjust = 100;//  (float)(m_pMaster->GetAttr(C_APDAMAGERATE) - pTarget->GetAttr(C_APREDUCEDAMAGERATE) + skillDamageAdjust) / 10000;
	//int32_t damagefix = 100;// m_pMaster->GetAttr(C_EXTRA_DAMAGE) - pTarget->GetAttr(C_REDUCE_DAMAGE) + skillDamgefix;

	int32_t eleAp = 0;
	int32_t tartgetDp = 0;
	if (pskillmeta->elementType == enSkillEleType_Fire)
	{
		eleAp = pSource->GetAttr(C_FIREATT);
		tartgetDp = pTarget->GetAttr(C_FIREDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Ice)
	{
		eleAp = pSource->GetAttr(C_ICEATT);
		tartgetDp = pTarget->GetAttr(C_ICEDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Wind)
	{
		eleAp = pSource->GetAttr(C_WINDATT);
		tartgetDp = pTarget->GetAttr(C_WINDDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Earth)
	{
		eleAp = pSource->GetAttr(C_SOLATT);
		tartgetDp = pTarget->GetAttr(C_SOLDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Thunder)
	{
		eleAp = pSource->GetAttr(C_RAYATT);
		tartgetDp = pTarget->GetAttr(C_RAYDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Poison)
	{
		eleAp = pSource->GetAttr(C_POISONATT);
		tartgetDp = pTarget->GetAttr(C_POISONDEF);
	}
	////技能伤害调整百分比
	int32_t apDamagePer = skillDamageAdjust;
	//其它等级压制
	int32_t levelOther = GetLevelSuppress(pSource, pTarget);
	
	//其他伤害调整百分比
	int32_t  otherdamagePer = eleAp + levelOther + pSource->GetAttr(C_PHYDAMCHECK) - tartgetDp - pTarget->GetAttr(C_PHYDEFCHECK);
	otherdamagePer = otherdamagePer < g_constDamagePer ? g_constDamagePer : otherdamagePer;

	if (apDamagePer<g_constDamagePer)
	{
		apDamagePer = g_constDamagePer;
	}

	int32_t apDamageFix = skillDamgefix + pSource->GetAttr(C_PHYEXTRADAMAGE) - pTarget->GetAttr(C_PHYREDUCEDAMAGE);


	bool bcirt = CalculateCritAp(pSource, pClientTarget, pTarget, damage, focoTime);

	//物理暴击伤害调整百分比
	uint32_t baojiRate = 0;
	//物理暴击伤害调整固定值
	uint32_t baojiFix = 0;
	if (bcirt)
	{
		baojiRate = pSource->GetAttr(C_PHYCRITMUL);
		baojiFix = pSource->GetAttr(C_PHYCRITEXTRA) - pTarget->GetAttr(C_PHYCRITREDUCE);
	}


	int32_t baseAd = (cAp - cDp*g_constSKillAdjust);
	if (baseAd > 0.1*cAp)
	{
		damage = baseAd*(1 + apDamagePer / 10000.0f)*(1 + otherdamagePer / 10000.0f + baojiRate / 10000.0f) + apDamageFix + baojiFix;
	}
	else
		damage = (0.09*cAp*cAp / (cDp*g_constSKillAdjust))*(1 + apDamagePer / 10000.0f)*(1 + otherdamagePer / 10000.0f + baojiRate / 10000.0f) + apDamageFix + baojiFix;

	
	damage = damage <= 0 ? 1 : damage;

	pSource->BuffEffect_AddExtraDamage(pTarget, skillId, damage);
	pTarget->BuffEffect_ReduceDamage(pSource, skillId, damage);

	

	//伤害还原，只在此次技能有效
	pSource->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(m_pMaster->CreatureKind(), C_AP), 0);
	pSource->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(m_pMaster->CreatureKind(), C_APRATE), 0, true);

	//伤害属性同步
	//pTarget->AddAttr(C_HP, -damage, false, m_pMaster->GetCid());

	pClientTarget->set_bedead(pTarget->IsDead());
	Attr *pAttr = pClientTarget->add_creatureattr();
	pAttr->set_attrnum(pTarget->GetAttrNum(C_HP));

	if (pTarget->GetAttr(C_HP) - damage<0)
	{
		pAttr->set_attrvalue(0);
	}
	else
	{
		pAttr->set_attrvalue(pTarget->GetAttr(C_HP) - damage);
	}


	//同步死亡击飞状态
	if (pAttr->attrvalue() <= 0 && bcirt)
	{
		Monster * pMonster = dynamic_cast<Monster*>(pTarget);
		if (pMonster)
		{
			if (pMonster->UpdateDeadBeback())
			{
				pClientTarget->set_isdeadbeback(true);

				Vector3PB *pTransPos = new Vector3PB;
				Point3<float> tmpPos;
				tmpPos.x = pMonster->GetPos().x - pSource->GetPos().x;
				tmpPos.y = 0;
				tmpPos.z = pMonster->GetPos().z - pSource->GetPos().z;

				if (tmpPos.length()==0 )
				{
					tmpPos = pSource->GetPos();
				}
				pTransPos->set_x(tmpPos.x);
				pTransPos->set_y(tmpPos.y);
				pTransPos->set_z(tmpPos.z);
				pClientTarget->set_allocated_bebackdir(pTransPos);
			}
		}
	}
	

	//LogDebugFmtPrint("skillid=%d,damage=%d,ap=%d,mdp=%d", skillId, damage, cAp, cDp);

	DigPerfor* pdigti = pClientTarget->add_digperfors();
	pdigti->set_value(damage);

	if (damage==0)
	{
		pdigti->set_type(DigPerfor_Type_absorb);
	}
	else
	{
		//跳字表现数据
		if (false == bcirt)
			pdigti->set_type(DigPerfor_Type_reduceHp);
		else
			pdigti->set_type(DigPerfor_Type_cirit);
	}
	

	return damage;
}

uint32_t SkillPart::CalculateMat(Creature *pSource,UseSkillResult::Target *pClientTarget, Creature *pTarget, const SkillCfg* pskillmeta, uint32_t damagePoint, uint32_t focoTime)
{
	//伤害计算
	int32_t damage = 0;
//	uint32_t userId = m_pMaster->GetCid();
	//uint32_t targetId = pTarget->GetCid();
	uint32_t skillId = pskillmeta->skillID;
	int32_t skillDamageAdjust = 0;
	//BEGIN_PROFILE("SkillPart::GetSkillAttackPercent");
	skillDamageAdjust = GetSkillAttackPercent(skillId, damagePoint,pTarget);		//  附加伤害调整百分比 FuncLua(skillId, pskillmeta->funcDamageRate, damagePoint, userId, targetId, focoTime);
	//END_PROFILE();
	int32_t skillDamgefix = GetSkillHurtFix(skillId, damagePoint,pTarget);			//	附加伤害固定值	FuncLua(skillId, pskillmeta->funcDamageValue, damagePoint, userId, targetId, focoTime);
	int32_t skillAttackAdjust = GetSkillHurtPercent(skillId, damagePoint,pTarget);		//	附加攻击调整百分比	FuncLua(skillId, pskillmeta->funcAttackRate, damagePoint, userId, targetId, focoTime);
	int32_t skillAttackfix = GetSkillAttackfix(skillId, damagePoint,pTarget);			//	附加攻击值	FuncLua(skillId, pskillmeta->funcAttackValue, damagePoint, userId, targetId, focoTime);

	//BEGIN_PROFILE("m_pMaster->SetAttr");
	pSource->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(m_pMaster->CreatureKind(), C_MP), skillAttackfix);
	pSource->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(m_pMaster->CreatureKind(), C_MATRATE), skillAttackAdjust, true);
	//END_PROFILE();

	int32_t cMat = pSource->GetAttr(C_MAT);
	int32_t cMdp = pTarget->GetAttr(C_MDP); 

	//float damageAdjust = 100; //(float)(m_pMaster->GetAttr(C_MATDAMAGERATE) - pTarget->GetAttr(C_MATREDUCEDAMAGERATE) + skillDamageAdjust) / 10000;
	//int32_t damagefix = 100;// m_pMaster->GetAttr(C_EXTRA_DAMAGE) - pTarget->GetAttr(C_REDUCE_DAMAGE) + skillDamgefix;


	int32_t eleAp = 0;
	int32_t tartgetDp = 0;
	if (pskillmeta->elementType == enSkillEleType_Fire)
	{
		eleAp = pSource->GetAttr(C_FIREATT);
		tartgetDp = pTarget->GetAttr(C_FIREDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Ice)
	{
		eleAp = pSource->GetAttr(C_ICEATT);
		tartgetDp = pTarget->GetAttr(C_ICEDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Wind)
	{
		eleAp = pSource->GetAttr(C_WINDATT);
		tartgetDp = pTarget->GetAttr(C_WINDDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Earth)
	{
		eleAp = pSource->GetAttr(C_SOLATT);
		tartgetDp = pTarget->GetAttr(C_SOLDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Thunder)
	{
		eleAp = pSource->GetAttr(C_RAYATT);
		tartgetDp = pTarget->GetAttr(C_RAYDEF);
	}
	else if (pskillmeta->elementType == enSkillEleType_Poison)
	{
		eleAp = pSource->GetAttr(C_POISONATT);
		tartgetDp = pTarget->GetAttr(C_POISONDEF);
	}
	////源物理伤害调整百分比
	int32_t apDamagePer = skillDamageAdjust;
	int32_t levelOther = GetLevelSuppress(pSource, pTarget);
	int32_t  otherdamagePer = eleAp + levelOther - tartgetDp + pSource->GetAttr(C_MAGDAMCHECK) - pTarget->GetAttr(C_MAGDEFCHECK);
	otherdamagePer = otherdamagePer  < g_constDamagePer ? g_constDamagePer : otherdamagePer;
	if (apDamagePer < g_constDamagePer)
	{
		apDamagePer = g_constDamagePer;
	}

	int32_t apDamageFix = skillDamgefix + pSource->GetAttr(C_MAGEXTRADAMAGE) - pTarget->GetAttr(C_MAGREDUCEDAMAGE);



	bool bcirt = CalculateCritMat(pSource, pClientTarget, pTarget, damage, focoTime);

	//物理暴击伤害调整百分比
	uint32_t baojiRate = 0;
	//物理暴击伤害调整固定值
	uint32_t baojiFix = 0;
	if (bcirt)
	{
		baojiRate = pSource->GetAttr(C_MAGCRITMUL);
		baojiFix = pSource->GetAttr(C_MAGCRITEXTRA) - pTarget->GetAttr(C_MAGCRITREDUCE);
	}


	int32_t baseAd = (cMat - cMdp*g_constSKillAdjust);
	if (baseAd > 0.1*cMat)
	{
		damage = baseAd*(1 + apDamagePer / 10000.0f)*(1 + otherdamagePer / 10000.0f + baojiRate / 10000.0f) + apDamageFix + baojiFix;
	}
	else
		damage = (0.09*cMat*cMat / (cMdp*g_constSKillAdjust))*(1 + apDamagePer / 10000.0f)*(1 + otherdamagePer / 10000.0f + baojiRate / 10000.0f) + apDamageFix + baojiFix;

	//bool bcirt = false;
	//BEGIN_PROFILE("SkillPart::CalculateCrit");
	//bcirt = CalculateCritMat(pSource,pClientTarget, pTarget, damage, focoTime);
	//END_PROFILE();
	
	damage = damage <= 0 ? 1 : damage;
	//BEGIN_PROFILE("SkillPart::BuffEffect_AddExtraDamage");
	//把buff中的加进去
	pSource->BuffEffect_AddExtraDamage(pTarget, skillId, damage);
	pTarget->BuffEffect_ReduceDamage(pSource, skillId, damage);

	
	//END_PROFILE();
	////伤害属性同步
	//pTarget->AddAttr(C_HP, -damage, false , m_pMaster->GetCid());

	//放完技能，还原技能影响的值
	pSource->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(m_pMaster->CreatureKind(), C_MP), 0);
	pSource->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(m_pMaster->CreatureKind(), C_MATRATE), 0, true);


	Attr *pAttr = NULL;
	//BEGIN_PROFILE("SkillPart::probuff1111");
	pClientTarget->set_bedead(pTarget->IsDead());
	pAttr = pClientTarget->add_creatureattr();
	pAttr->set_attrnum(pTarget->GetAttrNum(C_HP));

	if (pTarget->GetAttr(C_HP)-damage<0)
	{
		pAttr->set_attrvalue(0);
	}
	else
	{
		pAttr->set_attrvalue(pTarget->GetAttr(C_HP) - damage);
	}
	

	//LogDebugFmtPrint("skillid=%d,damage=%d,mp=%d,mdp=%d", skillId, damage, cMat, cMdp);

	//END_PROFILE();

	//BEGIN_PROFILE("SkillPart::probuff2222");
	//同步死亡击飞状态
	if (pAttr->attrvalue() <= 0 && bcirt)
	{
		Monster * pMonster = dynamic_cast<Monster*>(pTarget);
		if (pMonster)
		{
			if (pMonster->UpdateDeadBeback())
			{
				pClientTarget->set_isdeadbeback(true);

				Vector3PB *pTransPos = new Vector3PB;
				Point3<float> tmpPos;
				tmpPos.x = pMonster->GetPos().x - pSource->GetPos().x;
				tmpPos.y = 0;
				tmpPos.z = pMonster->GetPos().z - pSource->GetPos().z;

				if (tmpPos.length() == 0)
				{
					tmpPos = pSource->GetPos();
				}
				pTransPos->set_x(tmpPos.x);
				pTransPos->set_y(tmpPos.y);
				pTransPos->set_z(tmpPos.z);
				pClientTarget->set_allocated_bebackdir(pTransPos);
			}
		}
	}

	

	DigPerfor* pdigti = pClientTarget->add_digperfors();
	pdigti->set_value(damage);

	if (damage == 0)
	{
		pdigti->set_type(DigPerfor_Type_absorb);
	}
	else
	{
		//跳字表现数据
		if (false == bcirt)
			pdigti->set_type(DigPerfor_Type_reduceHp);
		else
			pdigti->set_type(DigPerfor_Type_cirit);
	}
	

	//END_PROFILE();
	return damage;
}

uint32_t SkillPart::CalculateHeal(UseSkillResult::Target *pClientTarget, Creature *pTarget, const SkillCfg* pskillmeta, uint32_t damagePoint, uint32_t focoTime)
{

	//伤害计算
	//int32_t damage = 0;
	////	uint32_t userId = m_pMaster->GetCid();
	////uint32_t targetId = pTarget->GetCid();
	//uint32_t skillId = pskillmeta->skillID;

	//int32_t skillDamageAdjust = GetSkillAttackPercent(skillId, damagePoint);		//  附加伤害调整百分比 FuncLua(skillId, pskillmeta->funcDamageRate, damagePoint, userId, targetId, focoTime);
	//int32_t skillDamgefix = 0;			//	附加伤害固定值	FuncLua(skillId, pskillmeta->funcDamageValue, damagePoint, userId, targetId, focoTime);
	//int32_t skillAttackAdjust = 0;		//	附加攻击调整百分比	FuncLua(skillId, pskillmeta->funcAttackRate, damagePoint, userId, targetId, focoTime);
	//int32_t skillAttackfix = GetSkillAttackfix(skillId, damagePoint);			//	附加攻击值	FuncLua(skillId, pskillmeta->funcAttackValue, damagePoint, userId, targetId, focoTime);

	//m_pMaster->SetAttr(C_SKILL_FIX_MAT, skillAttackfix);
	//m_pMaster->SetAttr(C_SKILL_PERCENT_MAT, skillAttackAdjust);

	//int32_t cMat = m_pMaster->GetAttr(C_MAT);
	//int32_t cMdp = pTarget->GetAttr(C_MDP);

	//float damageAdjust = (float)(m_pMaster->GetAttr(C_MATDAMAGERATE) - pTarget->GetAttr(C_MATREDUCEDAMAGERATE) + skillDamageAdjust) / 10000;
	//int32_t damagefix = m_pMaster->GetAttr(C_EXTRA_DAMAGE) - pTarget->GetAttr(C_REDUCE_DAMAGE) + skillDamgefix;

	//int32_t baseAp = cMat - cMdp*g_constSKillAdjust;
	//if (baseAp > 0.1*cMat)
	//{
	//	damage = baseAp*(1 + damageAdjust) + damagefix;
	//}
	//else
	//	damage = (0.09*cMat*cMdp / (cMdp*g_constSKillAdjust))*(1 + damageAdjust) + damagefix;

	////把buff中的加进去
	//m_pMaster->BuffEffect_AddExtraDamage(pTarget, skillId, damage);
	//pTarget->BuffEffect_ReduceDamage(m_pMaster, skillId, damage);




	//pClientTarget->set_bedead(pTarget->IsDead());
	//Attr *pAttr = pClientTarget->add_creatureattr();
	//pAttr->set_attrnum(pTarget->GetAttrNum(C_HP));


	//pAttr->set_attrvalue(pTarget->GetAttr(C_HP) + damage);
	//

	//DigPerfor* pdigti = pClientTarget->add_digperfors();
	//pdigti->set_value(damage);

	////跳字表现数据
	//pdigti->set_type(DigPerfor_Type_addHp);

	////外面要加，所以这里用负的，--得+
	//return -damage;
	return 0;
}

bool SkillPart::CalculateCritAp(Creature *pSource,UseSkillResult::Target *pClientTarget, Creature *pTarget, int32_t& damage, uint32_t focoTime)
{
	int32_t diffLev = pSource->GetAttr(C_LEVEL) - pTarget->GetAttr(C_LEVEL);
	
	
	bool isFuShu = false;
	if (diffLev<0)
	{
		isFuShu = true;
	}
	diffLev = diffLev > 0 ? diffLev : -diffLev;

	const AttributeSuppressCfgInfo *pSuppress = g_GetAttributeSuppressCfgTable()->GetAttributeSuppressCfgInfo(diffLev);

	int32_t critSuppress = 0;
	if (pSuppress)
		critSuppress = pSuppress->critSuppress;
	
	if (isFuShu)
	{
		critSuppress = -1 * critSuppress;
	}

	float critRate = 1;
	
	if (pSource->GetAttr(C_PHYCRIT) + pTarget->GetAttr(C_PHYTOUGHNESS)*g_constThughnessPara >0)
	{
		critRate = (pSource->GetAttr(C_PHYCRIT) / (pSource->GetAttr(C_PHYCRIT) + pTarget->GetAttr(C_PHYTOUGHNESS)*g_constThughnessPara)) + pSource->GetAttr(C_PHYCRITRATE) / 10000.0f - pTarget->GetAttr(C_PHYTOUGHNESSRATE) / 10000.0f + critSuppress / 10000.0f;
	}
	
	
	if (critRate>0.6)  //最低1%
	{
		critRate = 0.6;
	}
	else if (critRate<0.01)
	{
		critRate = 0.01;
	}

	int32_t rate  = Random(1, 100);
	if (rate > (int32_t)(critRate*100))
		return false;

	//int32_t critAdjust = pSource->GetAttr(C_PHYCRITEXTRA) - pTarget->GetAttr(C_PHYCRITREDUCE);
	//int32_t tmpRate = pSource->GetAttr(C_PHYCRITMUL);
	//if (tmpRate<4000)
	//{
	//	tmpRate = 4000;
	//}
	//damage = damage*(1 + tmpRate / 10000.0f) + critAdjust;

	return true;
}

//魔法暴击计算
bool SkillPart::CalculateCritMat(Creature *pSource,UseSkillResult::Target *pClientTarget, Creature *pTarget, int32_t &damage, uint32_t focoTime)
{
	int32_t diffLev = pSource->GetAttr(C_LEVEL) - pTarget->GetAttr(C_LEVEL);
	bool isFuShu = false;
	if (diffLev<0)
	{
		isFuShu = true;
	}
	diffLev = diffLev > 0 ? diffLev : -diffLev;
	const AttributeSuppressCfgInfo *pSuppress = g_GetAttributeSuppressCfgTable()->GetAttributeSuppressCfgInfo(diffLev);

	int32_t critSuppress = 0;
	if (pSuppress)
		critSuppress = pSuppress->critSuppress;


	if (isFuShu)
	{
		critSuppress = -1 * critSuppress;
	}

	float critRate = 0; 

	if (pSource->GetAttr(C_MAGCRIT) + pTarget->GetAttr(C_MAGTOUGHNESS)*g_constThughnessPara == 0)
	{
		critRate = 1;
	}
	else
	{
		critRate = (pSource->GetAttr(C_MAGCRIT) / (pSource->GetAttr(C_MAGCRIT) + pTarget->GetAttr(C_MAGTOUGHNESS)*g_constThughnessPara)) + pSource->GetAttr(C_MAGCRITRATE) / 10000.0f - pTarget->GetAttr(C_MAGTOUGHNESSRATE) / 10000.0f + critSuppress / 10000.0f;
	}

	if (critRate > 0.6)  //最低1%
	{
		critRate = 0.6;
	}
	else if (critRate<0.01)
	{
		critRate = 0.01;
	}

	int32_t rate = Random(1, 100);
	if (rate > (int32_t)(critRate*100))
		return false;

	//int32_t critAdjust = pSource->GetAttr(C_MAGCRITEXTRA) - pTarget->GetAttr(C_MAGCRITREDUCE);
	//int32_t tmpRate = pSource->GetAttr(C_MAGCRITMUL);
	//if (tmpRate < 4000)
	//{
	//	tmpRate = 4000;
	//}
	//damage = damage*(1 + tmpRate / 10000.0f) + critAdjust;

	return true;
}

bool SkillPart::CalculateHitAp(Creature *pSource,UseSkillResult::Target *pClientTarget, Creature *pTarget, const SkillCfg* pskillmeta, uint32_t focoTime)
{
	int32_t diffLev = pSource->GetAttr(C_LEVEL) - pTarget->GetAttr(C_LEVEL);

	bool isFuShu = false;
	if (diffLev<0)
	{
		isFuShu = true;
	}
	diffLev = diffLev > 0 ? diffLev : -diffLev;
	const AttributeSuppressCfgInfo *pSuppress = g_GetAttributeSuppressCfgTable()->GetAttributeSuppressCfgInfo(diffLev);

	int32_t hitSuppress = 0;
	if (pSuppress)
		hitSuppress = pSuppress->hitSuppress;
	if (isFuShu)
	{
		hitSuppress = -1 * hitSuppress;
	}

	float hitRate = 1;
	if (pSource->GetAttr(C_PHYHIT) + pTarget->GetAttr(C_PHYDODGE)*g_constDodgePara >0)
	{
		hitRate = (pSource->GetAttr(C_PHYHIT) / (pSource->GetAttr(C_PHYHIT) + pTarget->GetAttr(C_PHYDODGE)*g_constDodgePara)) - pTarget->GetAttr(C_PHYDODGERATE) / 10000.0f + pSource->GetAttr(C_PHYHITRATE) / 10000.0f + hitSuppress / 10000.0f;
	}
	
	hitRate = hitRate < 0.4 ? 0.4 : hitRate;
	uint32_t rate = Random(1, 100);
	if (rate > hitRate*100)
	{
		DigPerfor* pdigti = pClientTarget->add_digperfors();
		pdigti->set_type(DigPerfor_Type_doge);
		return false;
	}

	return true;
}

//魔法伤害技能命中
bool SkillPart::CalculateHitMat(Creature *pSource,UseSkillResult::Target *pClientTarget, Creature *pTarget, const SkillCfg* pskillmeta, uint32_t focoTime)
{
	int32_t diffLev = pSource->GetAttr(C_LEVEL) - pTarget->GetAttr(C_LEVEL);
	bool isFuShu = false;
	if (diffLev<0)
	{
		isFuShu = true;
	}
	diffLev = diffLev > 0 ? diffLev : -diffLev;
	const AttributeSuppressCfgInfo *pSuppress = g_GetAttributeSuppressCfgTable()->GetAttributeSuppressCfgInfo(diffLev);

	int32_t hitSuppress = 0;
	if (pSuppress)
		hitSuppress = pSuppress->hitSuppress;
	if (isFuShu)
	{
		hitSuppress = -1 * hitSuppress;
	}

	float hitRate = 1;
	if (pSource->GetAttr(C_MAGHIT) + pTarget->GetAttr(C_MAGDODGE)*g_constDodgePara>0)
	{
		hitRate = (pSource->GetAttr(C_MAGHIT) / (pSource->GetAttr(C_MAGHIT) + pTarget->GetAttr(C_MAGDODGE)*g_constDodgePara)) - pTarget->GetAttr(C_MAGDODGERATE) / 10000.0f + pSource->GetAttr(C_MAGHITRATE) / 10000.0f + hitSuppress / 10000.0f;
	}
	
	hitRate = hitRate < 0.4 ? 0.4 : hitRate;
	uint32_t rate = Random(1, 100);
	if (rate > hitRate*100)
	{
		DigPerfor* pdigti = pClientTarget->add_digperfors();
		pdigti->set_type(DigPerfor_Type_doge);
		return false;
	}

	return true;
}


bool SkillPart::SaveDB(CharacterDBInfo& characterDB)
{
	CharacterDBSkillData *pSkillData = new CharacterDBSkillData;
	mapSkillInfo::iterator iter = m_mapskills.begin();
	for (; iter != m_mapskills.end(); iter++)
	{
		if (iter->second._enSaveType == enSkillSaveType_SaveDB)
		{
			CharacterDBSkillItem *pskill = pSkillData->add_skilllist();
			pskill->set_skillid(iter->second._Id);
			pskill->set_skilllevel(iter->second._level);
			pskill->set_cd(iter->second._cdTimeStamps);
		}
	}
	characterDB.set_allocated_skilldata(pSkillData);
	return true;
}

bool SkillPart::C2LevUpSkill(const char* data, uint32_t len)
{

	const FunctionunlockFunctionUnlockCfgInfo * pConfig=g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_SKILL);

	if (pConfig && m_pMaster->GetPAttrValue(P_LEVEL) < pConfig->unlockLevel)
	{
		LogDebugFmtPrint("level=%d skill not open ", m_pMaster->GetPAttrValue(P_LEVEL));
		return false;
	}

	LevUpSkillReq lsReq;
	if (!lsReq.ParseFromArray(data, len))
		return false;

	uint32_t skillId = lsReq.skillid();
	stSkillInfo* pSkill = GetSkillInfo(skillId);
	if (!pSkill)
	{
		LogErrFmtPrint("learn Skill dont have this skill, Id:%d, cid:%d", skillId, m_pMaster->GetCid());
		return false;
	}

	LevUpSkillRsp lsRsp;
	int cLev = m_pMaster->GetAttr(C_LEVEL);
	if (pSkill->_pSkillmeta->minLevel.size() == pSkill->_level)
	{
		lsRsp.set_code(RET_DEPUTY_SKILL_MAX_LEVEL_LIMIT);
		m_pMaster->SendDataToClient(LOGIC_TO_CLIENT_SKILL_LEVEL_UP_RSP, &lsRsp);
		return false;
	}
	else if (pSkill->_pSkillmeta->minLevel.size() < pSkill->_level-1 || pSkill->_pSkillmeta->minLevel[pSkill->_level] > cLev)
	{
		lsRsp.set_code(RET_SKILL_CHARACTER_LEVEL_LOW);
		m_pMaster->SendDataToClient(LOGIC_TO_CLIENT_SKILL_LEVEL_UP_RSP, &lsRsp);
		return false;
	}

	
	//配置有错
	if ((uint32_t)pSkill->_pSkillmeta->updateCostValue.size()< pSkill->_level)
	{
		LogErrFmtPrint("level=%d upcosterror size=%d ", pSkill->_level + 1, pSkill->_pSkillmeta->updateCostValue.size());
		return false;
	}


	//扣消耗
	double value = pSkill->_pSkillmeta->updateCostValue[pSkill->_level - 1]; // GetValueFromFormula(skillId, (VEC_INT32&)pSkill->_pSkillmeta->updateCostValue);
	if (value > m_pMaster->GetAttr(C_GOLD))
	{
		lsRsp.set_code(RET_GOLD_LACK);
		return m_pMaster->SendDataToClient(LOGIC_TO_CLIENT_SKILL_LEVEL_UP_RSP, &lsRsp);
	}
	

	//m_pMaster->AddAttr(C_GOLD, -1 * (int64_t)value, true);
	m_pMaster->AddSourceAttr(C_GOLD, -1 * (int64_t)value, true, S_SKILL_LEVEL);
	pSkill->_level++;
	lsRsp.set_code(RET_SUCCESS);
	lsRsp.set_skillid(skillId);
	lsRsp.set_skilllev(pSkill->_level);

	pSkill->_fightValue = GetSkillFightValue(skillId);

	//升级，重新计算战斗力事件
	CalcFightPowerEvent calcFightPower;
	calcFightPower.cid = m_pMaster->GetCid();

	//通知攻击者和受害者攻击事件
	g_GetEvent()->FireExecute(EVENT_CALC_FIGHT_POWER, m_pMaster->GetCid(), CREATURE_PLAYER, (CalcFightPowerEvent*)&calcFightPower, sizeof(CalcFightPowerEvent));
	m_pMaster->SynAttrToClient();


	//发送技能升级事件0
	playerSkillUpEvent skillLevelUp;
	skillLevelUp.skillID = skillId;
	skillLevelUp.level = pSkill->_level;
	g_GetEvent()->FireExecute(EVENT_SKILL_UP, m_pMaster->GetCid(), CREATURE_PLAYER, (playerSkillUpEvent*)&skillLevelUp, sizeof(playerSkillUpEvent));

	return m_pMaster->SendDataToClient(LOGIC_TO_CLIENT_SKILL_LEVEL_UP_RSP, &lsRsp);
}

void SkillPart::RegisterPassiveSkill(SkillBase* pSkill)
{
	//判断是否是被动技能
	//if (pSkill->pSkillmeta->xxxx)
	//return;

	//pSkill->pSkillmeta->type
}


bool SkillPart::AddSkill(uint32_t skillId, uint32_t lev, CharIDType cd /* = 0 */, uint32_t priority /* = 0 */, bool calcFightPower, bool isNoticeClient, enSkillSaveType type)
{
	stSkillInfo* pSkill = GetSkillInfo(skillId);
	if (pSkill)
	{
		LogDebugFmtPrint("creature already have this skillId:%d, no need add, Cid:%llu,configid=%d", skillId, m_pMaster->GetCid(),m_pMaster->GetConfigId());
		return true;
	}

	stSkillInfo skill;
	skill._pSkillmeta = g_GetSkillMgr()->GetSkillCfg(skillId);
	if (!skill._pSkillmeta)
	{
		LogErrFmtPrint("skill metacfg is null, skillid:%d", skillId);
		return false;
	}
	
	//如果是被动技能，则直接使用
	if (IsPassiveSkill(skill._pSkillmeta))
	{
		//vecUint64_t vecTarget;
		//vecTarget.push_back(m_pMaster->GetCid());
		//BeginCreatureUseSkill(skillId, vecTarget, m_pMaster->GetDir(), m_pMaster->GetPos());
		AddStateBag(skillId, lev, m_pMaster);

		if (type != enSkillSaveType_UseOnce)
		{
			skill._Id = skillId;
			skill._level = lev;
			skill._cdTimeStamps = cd;
			skill._priority = priority;
			skill._enSaveType = type;
			m_mapskills[skillId] = skill;
			m_mapskills[skillId]._fightValue = GetSkillFightValue(skillId);
		}
	}
	else
	{

		if (skill._pSkillmeta->minLevel.size() > 0 && skill._pSkillmeta->minLevel[0] <= (int32_t)m_pMaster->GetPAttrValue(P_LEVEL))
		{
			skill._isUnLock = true;
		}

		skill._Id = skillId;
		skill._level = lev;
		skill._cdTimeStamps = cd;
		skill._priority = priority;

		//把该技能的关联技能全加上
		const SkillCfg* pTmpSkillCfg = skill._pSkillmeta;
		while (pTmpSkillCfg && pTmpSkillCfg->relationSkillId>0)
		{
			skill._vRelatedSkill.push_back(pTmpSkillCfg->relationSkillId);
			pTmpSkillCfg = g_GetSkillMgr()->GetSkillCfg(pTmpSkillCfg->relationSkillId);
		}

		//如果是玩家，通知添加技能
		if (m_pMaster->CreatureKind() == CREATURE_PLAYER && isNoticeClient)
		{
			SkillAddRsp rsp;
			SkillCell * pSkillCell=rsp.mutable_skillinfo();
			pSkillCell->set_skillid(skillId);
			pSkillCell->set_skilllev(lev);
			pSkillCell->set_cd(0);
			m_pMaster->SendDataToClient(LOGIC_TO_CLIENT_ADD_SKILL, &rsp);
		}


		skill._enSaveType = type;
		m_mapskills[skillId] = skill;
		m_mapskills[skillId]._fightValue = GetSkillFightValue(skillId);
	}
	
	


	return true;
}

bool SkillPart::RemoveSkill(uint32_t skillId, bool isNoticeClient)
{
	stSkillInfo* pSkill = GetSkillInfo(skillId);
	if (!pSkill)
	{
		////被动技能找不到，是接口调用错，不用打印了
		//const SkillCfg* pConfig=g_GetSkillMgr()->GetSkillCfg(skillId);
		//if (pConfig && !IsPassiveSkill(pConfig))
		//{
		//	LogErrFmtPrint("creature havnt this skill, cannt remove skillId, cid:%llu", skillId, m_pMaster->GetCid());
		//}
		
		return false;
	}
	//if (pSkill->_pSkillmeta->profession != SkillPro_Remove)
	//	return false;

	//pSkill->refreshData();
	
	//移除时，把已加上的buff移掉
	BuffPart* pBuffPart = dynamic_cast<BuffPart*>(m_pMaster->GetPart(PART_BUFF));
	if (pBuffPart && IsPassiveSkill(pSkill->_pSkillmeta))
	{
		pBuffPart->BuffEffect_CleanupAllFadeOutEffects(skillId);
	}

	if (m_pMaster->CreatureKind() == CREATURE_PLAYER)
	{
		if (!IsPassiveSkill(pSkill->_pSkillmeta) && isNoticeClient)
		{
			//如果是玩家，通知移除技能
			SkillDeleteRsp rsp;
			SkillCell * pSkillCell = rsp.mutable_skillinfo();
			pSkillCell->set_skillid(skillId);
			pSkillCell->set_skilllev(pSkill->_level);
			pSkillCell->set_cd(0);
			m_pMaster->SendDataToClient(LOGIC_TO_CLIENT_DELETE_SKILL, &rsp);
		}
		
	
		////发送计算事件
		//CalcFightPowerEvent calcFightPower;
		//calcFightPower.cid = m_pMaster->GetCid();

		////通知攻击者和受害者攻击事件
		//g_GetEvent()->FireExecute(EVENT_CALC_FIGHT_POWER, m_pMaster->GetCid(), CREATURE_PLAYER, (CalcFightPowerEvent*)&calcFightPower, sizeof(CalcFightPowerEvent));
	}

	m_mapskills.erase(skillId);
	return true;
}

bool SkillPart::AddStateBag(uint32_t skllId, uint32_t lev, Creature* pTarget /* = nullptr */)
{
	const SkillCfg* pSkillmeta = g_GetSkillMgr()->GetSkillCfg(skllId);
	if (!pSkillmeta )  //pSkillmeta->profession != SkillPro_Statebag
	{
	//	LogErrFmtPrint("skillpart, add statebag error, profession:%d != %d", pSkillmeta->profession, SkillPro_Statebag);
		return false;
	}


	UseSkillResult useResult;
	useResult.set_skillid(skllId);
	useResult.set_usercid(m_pMaster->GetCid());

	if (!pTarget)
	{
		pTarget = m_pMaster;
	}

	Creature * pHandleCreature = pTarget;

	int32_t arg;
	int32_t time;
	//buff接口
	BuffPart* pBuffPart = dynamic_cast<BuffPart*>(pHandleCreature->GetPart(PART_BUFF));
	if (pBuffPart)
	{
		for (size_t i = 0; i < pSkillmeta->vStateBags.size(); i++)
		{
			SkillCfgStateBag stateBag = pSkillmeta->vStateBags[i];
			if (!IsHitStateBag(m_pMaster,pTarget, stateBag)) //未命中
			{
				continue;
			}

			std::vector<int32_t> vecParams;
			for (size_t j = 0; j < pSkillmeta->vStateBags[i].vParameter.size(); j++)
			{
				arg = GetStateBagParam(pSkillmeta->skillID, i, j, pHandleCreature, lev);    //m_pMaster->DoSkillString(pSkillmeta->skillID, lev, effectArgs[j].c_str(), m_pMaster->GetCid(), pHandleCreature->GetCid());
				vecParams.push_back(arg);
			}
			time = GetStateBagTimeParam(pSkillmeta->skillID,i,pHandleCreature);    // m_pMaster->DoSkillString(pSkillmeta->skillID, lev, pSkillmeta->vStateBags[i].Time.c_str(), m_pMaster->GetCid(), pHandleCreature->GetCid());
			
			pBuffPart->BuffEffect_RegisterEffect(m_pMaster, pSkillmeta->skillID, lev, 
				pSkillmeta->vStateBags[i].ID, pSkillmeta->vStateBags[i].Rate, time, vecParams, true, pSkillmeta->vStateBags[i].target);

			//if (pBuffBag)
			//{
			//	ProtoBuf::BuffBagDetailInfo* pClientStatebag = useResult.add_statebags();
			//	if (pClientStatebag)
			//	{
			//		pBuffBag->ToMsg(*pClientStatebag);
			//	}
			//}
			
		}

		//发送消息
		m_pMaster->BroadCastData(EMODULE_ID_SKILL, LOGIC_TO_CLIENT_SKILL_RESULT_BROADCAST, (ProtoBufBase*)&useResult, true);
	}
	else
		LogErrFmtPrint("skill calculate get target buffpart null, targetCid:%d", pTarget->GetCid());

	return true;
}

//直接移除状态包
bool SkillPart::RemoveStateBat(uint32_t skillId)
{
	BuffPart* pBuffPart = dynamic_cast<BuffPart*>(m_pMaster->GetPart(PART_BUFF));
	if (pBuffPart)
	{
		pBuffPart->BuffEffect_CleanupAllFadeOutEffects(skillId);
	}

	return true;
}

bool SkillPart::StateBagWithDamagePoint(Creature *pSource,const SkillCfg *pSkillmeta, uint32_t lev, UseSkillResult& useResult, Creature* pTarget, uint32_t Point, bool isNeedCalcuate)
{
	//BEGIN_PROFILE("SkillPart::StateBagWithDamagePoint");
	if (!pSkillmeta)
		return false;

	int32_t arg;
	int32_t time;
	BuffPart* pTargetBuffPart = dynamic_cast<BuffPart*>(pTarget->GetPart(PART_BUFF));
	BuffPart* pMasterBuffPart = dynamic_cast<BuffPart*>(pSource->GetPart(PART_BUFF));
	BuffPart* tmpBuffPart = NULL;
	Creature * tmpTarget = NULL;
	if (pTargetBuffPart)
	{
		for (size_t i = 0; i < pSkillmeta->vStateBags.size(); i++)
		{
			if ((int32_t)Point+1 != pSkillmeta->vStateBags[i].Point)
				continue;

			if (pSkillmeta->type != enSkillTargetType_FriendBuffer)
			{
				if (isNeedCalcuate && pSkillmeta->vStateBags[i].target == 1)  //如果是1表示强制给玩家的
				{
					tmpBuffPart = pMasterBuffPart;
					tmpTarget = m_pMaster;
				}
				else if (pSkillmeta->vStateBags[i].target == 1 || pTarget->GetCid() == pSource->GetCid())
				{
					continue;
				}
				else
				{
					tmpBuffPart = pTargetBuffPart;
					tmpTarget = pTarget;
				}
			}
			else
			{
				tmpBuffPart = pTargetBuffPart;
				tmpTarget = pTarget;
			}
			

			SkillCfgStateBag stateBag = pSkillmeta->vStateBags[i];
			if (!IsHitStateBag(pSource,tmpTarget, stateBag)) //未命中
			{
				continue;
			}

			std::vector<int32_t> vecParams;
			for (size_t j = 0; j < pSkillmeta->vStateBags[i].vParameter.size(); j++)
			{
				arg = GetStateBagParam(pSkillmeta->skillID, i, j, tmpTarget,lev);// m_pMaster->DoSkillString(pSkillmeta->skillID, lev, effectArgs[j].c_str(), m_pMaster->GetCid(), pTarget->GetCid());
				vecParams.push_back(arg);

				if (arg==0)
				{
					LogDebugFmtPrint("StateBagWithDamagePoint pSkillmetaid=:%d,i=%d,j=%d", pSkillmeta->skillID,i,j);
				}
			}

			time = GetStateBagTimeParam(pSkillmeta->skillID, i, tmpTarget);// m_pMaster->DoSkillString(pSkillmeta->skillID, lev, pSkillmeta->vStateBags[i].Time.c_str(), m_pMaster->GetCid(), pTarget->GetCid());

			//BEGIN_PROFILE("SkillPart::BuffEffect_RegisterEffect");
			tmpBuffPart->BuffEffect_RegisterEffect(m_pMaster, pSkillmeta->skillID, lev,
				pSkillmeta->vStateBags[i].ID, pSkillmeta->vStateBags[i].Rate, time, vecParams,true, pSkillmeta->vStateBags[i].target);//pSkillmeta->vStateBags[i].Time, vecParams);

			//if (pBuffBag)
			//{
			//	ProtoBuf::BuffBagDetailInfo* pClientStatebag = useResult.add_statebags();
			//	if (!pClientStatebag)
			//	{
			//		LogErrFmtPrint("StateBagWithDamagePoint is null, pls check protobuff, SkillId:%d", pSkillmeta->skillID);
			//		break;
			//	}
			//	pBuffBag->ToMsg(*pClientStatebag);
			//}
			//END_PROFILE();
		}
	}
	else
		LogErrFmtPrint("skill calculate get target buffpart null, targetCid:%d", pTarget->GetCid());

	//END_PROFILE();
	return true;
}

bool SkillPart::StateBagAll(Creature *pSource,const SkillCfg *pSkillmeta, uint32_t lev, UseSkillResult& useResult, Creature* pTarget, bool isNeedCalcuate)
{
	if (!pSkillmeta)
		return false;

	int32_t arg;
	int32_t time;
	BuffPart* pTargetBuffPart = dynamic_cast<BuffPart*>(pTarget->GetPart(PART_BUFF));
	BuffPart* pMasterBuffPart = dynamic_cast<BuffPart*>(pSource->GetPart(PART_BUFF));
	if (pTargetBuffPart)
	{
		BuffPart* tmpBuffPart = nullptr;
		Creature * pTmpTargetCreature = nullptr;
		for (size_t i = 0; i < pSkillmeta->vStateBags.size(); i++)
		{                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
			std::vector<int32_t> vecParams;
			if (pSkillmeta->type != enSkillTargetType_FriendBuffer)
			{
				if (isNeedCalcuate && pSkillmeta->vStateBags[i].target == 1)  //如果是1表示强制给玩家的
				{
					tmpBuffPart = pMasterBuffPart;
					pTmpTargetCreature = m_pMaster;
				}
				else if (pSkillmeta->vStateBags[i].target == 1 || pTarget->GetCid() == pSource->GetCid())
				{
					continue;
				}
				else
				{
					tmpBuffPart = pTargetBuffPart;
					pTmpTargetCreature = pTarget;
				}
			}
			else
			{
				tmpBuffPart = pTargetBuffPart;
				pTmpTargetCreature = pTarget;
			}


			SkillCfgStateBag stateBag = pSkillmeta->vStateBags[i];
			if (!IsHitStateBag(pSource,pTmpTargetCreature, stateBag)) //未命中
			{
				continue;
			}

			for (size_t j = 0; j < (size_t)pSkillmeta->vStateBags[i].vParameter.size(); j++)
			{
				arg = GetStateBagParam(pSkillmeta->skillID, i, j, pTmpTargetCreature,lev); //m_pMaster->DoSkillString(pSkillmeta->skillID, lev, effectArgs[j].c_str(), m_pMaster->GetCid(), pTarget->GetCid());
				vecParams.push_back(arg);
			}

			time = GetStateBagTimeParam(pSkillmeta->skillID, i, pTmpTargetCreature); //m_pMaster->DoSkillString(pSkillmeta->skillID, lev, pSkillmeta->vStateBags[i].Time.c_str(), m_pMaster->GetCid(), pTarget->GetCid());

			tmpBuffPart->BuffEffect_RegisterEffect(m_pMaster, pSkillmeta->skillID, lev,
				pSkillmeta->vStateBags[i].ID, pSkillmeta->vStateBags[i].Rate, time, vecParams,true, pSkillmeta->vStateBags[i].target);//pSkillmeta->vStateBags[i].Time, vecParams);

			//if (pBuffBag)
			//{
			//	ProtoBuf::BuffBagDetailInfo* pClientStatebag = useResult.add_statebags();
			//	if (!pClientStatebag)
			//	{
			//		LogErrFmtPrint("StateBagWithDamagePoint is null, pls check protobuff, SkillId:%d", pSkillmeta->skillID);
			//		break;
			//	}
			//	pBuffBag->ToMsg(*pClientStatebag);
			//}
		}
	}
	else
		LogErrFmtPrint("skill calculate get target buffpart null, targetCid:%d", pTarget->GetCid());

	return true;
}

bool SkillPart::C2UseSkill(const char* data, uint32_t len)
{
	//BEGIN_PROFILE("SkillPart::C2UseSkill");
	UseSkillReq useReq;
	if (!useReq.ParseFromArray(data, len))
		return false;


	Player * pPlayer = dynamic_cast<Player*>(m_pMaster);

	//先判断是否使用内挂，且是否在内挂有效期内
	if (useReq.has_isleigua() && useReq.isleigua() == 1)
	{
		if (pPlayer && !pPlayer->IsLeiGuaActiveTime())
		{
			//内挂时间已过，不能再挂机使用技能
			return false;
		}
	}

	uint32_t Id = useReq.skillid();
	
	vecUint64_t targetCids;
	for (int i = 0; i < useReq.targetcids_size(); i++)
	{
		targetCids.push_back(useReq.targetcids(i));
	}

	Point3<float> currentPos;
	if (useReq.has_currentpos())
	{
		currentPos.x = useReq.currentpos().x();
		currentPos.y = useReq.currentpos().y();
		currentPos.z = useReq.currentpos().z();
	}
	m_pMaster->SetPos(currentPos);

	Point3<float> targetPos;
	if (useReq.has_targetpos())
	{
		targetPos.x = useReq.targetpos().x();
		targetPos.y = useReq.targetpos().y();
		targetPos.z = useReq.targetpos().z();
	}
	Point3<float> dir(useReq.dir().x(), useReq.dir().y(), useReq.dir().z());
	//m_pMaster->SetDir(dir);
	//LogErrFmtPrint("client send pos(%f,%f)", targetPos.x, targetPos.z);
	BeginUseSkill(Id, targetCids, dir, targetPos);
	
	//END_PROFILE();
	return true;
}

bool SkillPart::C2StopUseSkill(const char* data, uint32_t len)
{
	UseSkillStop useReq;
	if (!useReq.ParseFromArray(data, len))
		return false;

	uint32_t Id = useReq.skillid();

	//根据技能ID，找到该技能对像
	mapSkillFightInfo::iterator iter = m_mapSkillFightInfo.begin();
	for (; iter != m_mapSkillFightInfo.end();++iter)
	{
		if (iter->second->GetSkillID()==Id)
		{

			//判断该技能是不是普通技能。暂时只处理普通技能的打断
			stSkillInfo* pSkillConfig=GetSkillInfo(Id);
			if (pSkillConfig && pSkillConfig->_pSkillmeta->skilltype == enSkillType_Nomal)
			{
				iter->second->SetStopStep(useReq.skillstep());
			}
			break;
		}
	}

	BroadcastUseSkillStop broadcaststopskillInfo;
	broadcaststopskillInfo.set_skillid(Id);
	broadcaststopskillInfo.set_usercid(m_pMaster->GetCid());
	broadcaststopskillInfo.set_stopstep(useReq.skillstep());

	m_pMaster->BroadCastData(EMODULE_ID_SKILL, LOGIC_TO_CLIENT_SKILL_STOP_USE, (ProtoBufBase*)&broadcaststopskillInfo);
	return true;
}


bool SkillPart::C2GetBuffList(const char* data, uint32_t len)
{
	ReqCreatureBuffList useReq;
	CreatureBuffListRsp Rsp;
	if (!useReq.ParseFromArray(data, len))
		return false;
	for (int i = 0; i < useReq.cid_size();++i)
	{
		Creature* pCreature = m_pMaster->GetScene()->GetCreature(useReq.cid(i));
		if (pCreature)
		{
			if (pCreature->CreatureKind()==CREATURE_NPC) //非战斗NPC，不响应
			{
				Npc * pNpc = dynamic_cast<Npc*>(pCreature);
				if (pNpc && pNpc->GetBattleInfo() == NULL)
				{
					continue;
				}
			}
			BuffPart * pBuff = dynamic_cast<BuffPart*>(pCreature->GetPart(PART_BUFF));
			if (pBuff)
			{
				msgBuffList * pData = Rsp.add_list();
				pData->set_cid(pCreature->GetCid());
				pBuff->GetAllBuffInfo(pData);
			}
		}
	}

	m_pMaster->SendDataToClient(EMODULE_ID_SKILL, LOGIC_TO_CLIENT_BUFF_LIST_RSP, (ProtoBufBase*)&Rsp);
	return true;
}


bool SkillPart::C2SyncSkillTargets(const char* data, uint32_t len)
{
	//g_GetServiceMgr().SetSKillDebug(true);
	//BEGIN_PROFILE("skill use");
	SyncSkillTargetList useReq;
	if (!useReq.ParseFromArray(data, len))
		return false;

	uint32_t skillid = useReq.skillid();
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillid);
	if (pConfig == NULL)
	{
		return false;
	}
	

	VEC_INT32 tmpParam;
	VEC_FLOAT tmpFloatParam;
	vector<double> args;
	for (size_t i = 0; i < pConfig->funcRangeTypeValue.size(); i++)
	{
		//m_pMaster->GetFormula(pConfig->funcRangeTypeValue[i].c_str(), tmpParam);
		//cArg = m_pMaster->DoSkillString(pSkillmeta->skillID, lev, pSkillmeta->funcRangeTypeValue[i].c_str(), userId, targetCid, focotime);
		//args.push_back((float)cArg/1000);
		tmpFloatParam.clear();
		for (int j = 0; j < (int)pConfig->funcRangeTypeValue[i].size(); ++j)
		{
			tmpFloatParam.push_back(pConfig->funcRangeTypeValue[i][j] / 1000.0);
		}

		//如果大于三个参数，表示是公式
		if ((int)args.size() >= 3)
		{
			double value = GetValueFromFormula(pConfig->skillID, tmpParam,m_pMaster);
			args.push_back(value);
		}
		else
		{
			for (int j = 0; j < (int)tmpFloatParam.size(); ++j)
			{
				args.push_back(tmpFloatParam[j]);
			}
		}
	}


	SkillBase * pSkill = GetSkillBySkillID(skillid);
	if (!pSkill)
	{
		//LogDebugFmtPrint("not find skill skillid=%d ",skillid);
		return false;
	}

	cList targetCids;
	//先看有没有需要服务器来找目标的客户端技能，即所有指定类型生效的技能都是需要服务器找目录的
	if ((int)pConfig->vTargetType.size()>0)
	{
		//重新找一次目标
		FindCreatures(pConfig, GetMasterPos(), pSkill->GetSkillDir(), m_pMaster->GetCid(), m_pMaster->GetPos(), pSkill->GetDamageTime(), pSkill->GetFocoTime(), targetCids);
	}
	else
	{
		for (int i = 0; i < useReq.targetcids_size(); i++)
		{
			Creature * pCreature = g_GetCreatureMgr()->GetCreature(useReq.targetcids(i));
			if (pCreature)
			{
				//每个判断距离,
				if (args.size()>0 && point3Length(m_pMaster->GetPos(), pCreature->GetPos()) > args[0] + pCreature->GetModelRadius() + MAX_POS_ALLOW_ERROR)
				{
					continue;
				}

				if (!IsCanBeAttackBySkill(skillid, useReq.targetcids(i), m_pMaster))
				{
					continue;
				}

				//判断是否是翻滚状态，翻滚不受技能处理
				MovePart * pPart = dynamic_cast<MovePart*>(m_pMaster->GetPart(PART_MOVE));
				if (pPart)
				{
					if (pPart->IsRoll())
					{
						continue;
					}
				}

				targetCids.push_back(useReq.targetcids(i));
			}
		}
	}

	//if (targetCids.size()>0)
	{
		pSkill->OnDamageTimedoPlayer(skillid, targetCids);
	}
	return true;
}



bool SkillPart::AddSkillcd(int32_t cdPercent, uint32_t skillId /* = 0 */)
{
//	int32_t leftTime = 0;
	//int64_t curTick = g_GetGlobalServerTime()->UnixSec();
	//uint32_t runTime = 0;
	if (skillId > 0)
	{
		stSkillInfo* pskill = GetSkillInfo(skillId);
		if (pskill)
		{
			pskill->_cdPercent += cdPercent;
			if (pskill->_cdTimeStamps > 0)
			{
				//leftTime = pskill->_pSkillmeta->cd - (curTick - pskill->_cdTimeStamps);
				//runTime = (leftTime*(10000 - cdPercent) / 10000);
				//pskill->_cdPercent = runTime;
				//KillTimedo(cdTimeIdPre + skillId);
				//SetTimedo(cdTimeIdPre + skillId, runTime, 1);
				float tmp = pskill->_cdPercent*pskill->_pSkillmeta->cd ;
				pskill->_cdTimeStamps -= tmp;
			}
		}
		else
			return false;
	}
	else
	{

		auto iter = m_mapskills.begin();
		auto iterEnd = m_mapskills.end();
		for (; iter != iterEnd; iter++)
		{
			stSkillInfo* pskill = GetSkillInfo(iter->first);
			if (pskill)
			{
				pskill->_cdPercent += cdPercent;
				if (pskill->_cdTimeStamps > 0)
				{
					//leftTime = pskill->_pSkillmeta->cd - (curTick - pskill->_cdTimeStamps);
					//runTime = (leftTime*(10000 - cdPercent) / 10000);
					//pskill->_cdPercent = curTick + runTime;
					//KillTimedo(cdTimeIdPre + skillId);
					//SetTimedo(cdTimeIdPre + skillId, runTime, 1);
					float tmp = pskill->_cdPercent*pskill->_pSkillmeta->cd ;
					pskill->_cdTimeStamps -= tmp;
				}
			}
			else
				return false;
		}
	}
	return true;
}


//获取技能方向
Point3<float> SkillPart::GetSkillDir(uint32_t skillID)
{
	//mapSkillFightInfo::iterator iter= m_mapSkillFightInfo.begin();
	//for (; iter != m_mapSkillFightInfo.end();++iter)
	//{
	//	if (iter->second->GetSkillID()==skillID)
	//	{
	//		return iter->second->GetSkillDir();
	//	}
	//}
	//return Point3<float>(0.0, 0.0, 0.0);
	return m_pMaster->GetDir();
}


//获取放技能时的玩家位置,暂时是玩家有位移时，记录放技能的位置
Point3<float> SkillPart::GetCreaturePreSkillPos(uint32_t skillID)
{
	//mapSkillFightInfo::iterator iter = m_mapSkillFightInfo.begin();
	//for (; iter != m_mapSkillFightInfo.end(); ++iter)
	//{
	//	if (iter->second->IsSameSkill(skillID))
	//	{
	//		return iter->second->GetMasterPos();
	//	}
	//}
	//return Point3<float>(0.0, 0.0, 0.0);
	return m_pMaster->GetPos();
}

uint32_t SkillPart::GetMinAttack(uint32_t skillId)
{
	stSkillInfo* pskill = GetSkillInfo(skillId);
	if (!pskill)
		return 0;
	return pskill->_pSkillmeta->attackMinDistance;
}

uint32_t SkillPart::GetMaxAttack(uint32_t skillId)
{
	stSkillInfo* pskill = GetSkillInfo(skillId);
	if (!pskill)
		return 0;
	return pskill->_pSkillmeta->attackDis;
}

uint32_t SkillPart::GetSkillLev(uint32_t skillId)
{
	stSkillInfo* pskill = GetSkillInfo(skillId);
	if (!pskill)
	{
		const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillId);
		if (pConfig == NULL)
		{
			return 0;
		}

		return 1;
	}
	return pskill->_level;
}

uint32_t SkillPart::GetMaxPrioritySkill()
{
	int32_t priority = -1;
	uint32_t skillId = 0;
	//先选择优先级大，且不cd
	for (mapSkillInfo::iterator iter = m_mapskills.begin(); iter != m_mapskills.end(); iter++)
	{
		const stSkillInfo& info = iter->second;
		if (info.GetLeftCDTime() > 0 || info._pSkillmeta->skilltype == enSkillType_Nomal)
		{
			continue;
		}

		if ((int32_t)info._priority > priority)
		{
			priority = (int32_t)info._priority;
			skillId = info._Id;
		}
	}

	return skillId;
}


int32_t SkillPart::GetSkillRangtype(uint32_t skillid)
{
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillid);
	if (pConfig == NULL)
	{
		return 0;
	}
	return pConfig->rangeType;
}


void     SkillPart::RemoveSkillFightInfo(int globelid)
{
	mapSkillFightInfo::iterator iter = m_mapSkillFightInfo.find(globelid);
	if (iter != m_mapSkillFightInfo.end())
	{
		////如果是不存盘的主动技，放完移除
		stSkillInfo* pskill = GetSkillInfo(iter->second->GetSkillID());
		if (pskill && pskill->_enSaveType == enSkillSaveType_UseOnce)
		{
			RemoveSkill(iter->second->GetSkillID(), false);
		}
		RecyleSkill(iter->second);
		m_mapSkillFightInfo.erase(iter);
	}
}

void	 SkillPart::RecyleSkill(SkillBase * pSkill)
{
	pSkill->refreshData();
	switch (pSkill->GetSkillFightType())
	{
	case SkillFightType_SkillBullet:
	{
		SkillBullet * pObj = dynamic_cast<SkillBullet*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pBulletPool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_SkillShadowStrike:
	{
		SkillShadowStrike * pObj = dynamic_cast<SkillShadowStrike*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pShadowPool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_SkillFlash:
	{
		SkillFlash * pObj = dynamic_cast<SkillFlash*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pFlashPool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_SkillSummon:
	{
		SkillSummon * pObj = dynamic_cast<SkillSummon*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pSummonPool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_SkillTuXi:
	{
		SkillTuXi * pObj = dynamic_cast<SkillTuXi*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pTuXiPool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_Collide:
	{
		SkillChongZhuang * pObj = dynamic_cast<SkillChongZhuang*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pChongZhungPool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_Gouzi:
	{
		SkillGouzi * pObj = dynamic_cast<SkillGouzi*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pGouziPool->FreeObj(pObj);
		}
	}
		break;
	case SKillFightType_Relive:
	{
		SkillRelive * pObj = dynamic_cast<SkillRelive*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pRelivePool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_SomeSummon:
	{
		SkillSomeSummon * pObj = dynamic_cast<SkillSomeSummon*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pSomeSummonPool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_SomeBulletOnePoint:
	{
		SkillSomeBulletOnePoineAoe * pObj = dynamic_cast<SkillSomeBulletOnePoineAoe*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pSomeBulletOnePointPool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_SomePointDelayAoe:
	{
		SkillSomePointDelayAoe * pObj = dynamic_cast<SkillSomePointDelayAoe*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pSomePointDelayAoePool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_MoveAOE:
	{
		SkillMoveAOE * pObj = dynamic_cast<SkillMoveAOE*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pSkillMoveAoePool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_ShareDamegeSkill:
	{
		SkillShareDamage * pObj = dynamic_cast<SkillShareDamage*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pShareDamagePool->FreeObj(pObj);
		}
	}
		break;
	case SkillFightType_LockSomeTarget:
	{
		SkillLockSomeTarget * pObj = dynamic_cast<SkillLockSomeTarget*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pLockTargetPool->FreeObj(pObj);
		}
	}
		break;
	default:
	{
		SkillBase * pObj = dynamic_cast<SkillBase*>(pSkill);
		if (pObj)
		{
			g_GetSkillMgr()->m_pBasePool->FreeObj(pObj);
		}
	}
	break;
	}
}

uint32_t SkillPart::FuncLua(uint32_t skillId, vector<string> vecStr, uint32_t dPoint, CharIDType userCid, CharIDType targetCid, uint32_t focotime)
{
	stSkillInfo *pskill = GetSkillInfo(skillId);
	if (!pskill)
		return 0;
	int32_t value = 0;
	if (vecStr.size() > dPoint)
		 value = m_pMaster->DoSkillString(skillId, pskill->_level, vecStr[dPoint].c_str(), userCid, targetCid, focotime);
	return value;
}

//获取CD剩余时间
int64_t SkillPart::GetSkillLeftCDTime(uint32_t skillId)
{
	stSkillInfo *pskill = GetSkillInfo(skillId);
	if (!pskill)
	{
		return 0;
	}

	return pskill->GetLeftCDTime();
}

//bool SkillPart::GetFormula(string str, VEC_INT32 &vOutParam)  const
//{
//	//std::string strDameage = funcAttackValue[damageCount];
//	CommonApi::StrReplace(str, ",<", "");
//	CommonApi::StrReplace(str, "<", "");
//	CommonApi::StrReplace(str, "(", "");
//	CommonApi::StrReplace(str, ")", "");
//	str = CommonApi::StrLTrim(str);
//	str = CommonApi::StrRTrim(str);
//
//	CommonApi::SplitStrToVecInt(str, ",", &vOutParam);
//	return true;
//}
//根据公式，算出最终值
double SkillPart::GetValueFromFormula(uint32_t skillid, VEC_INT32 & vParam, Creature * pTargetCreature, uint32_t skillLev)
{
	int32_t skilllevel = 0;
	if (skillLev>0)
	{
		skilllevel = skillLev;
	}
	else
	{
		skilllevel = GetSkillLev(skillid);
	}
		

	double resultDamage = 0;

	if ((int)vParam.size() == 0)
	{
		return resultDamage;
	}
	else if ((int)vParam.size()==1)
	{
		resultDamage = vParam[0];
	}
	else
	{
		//根据第一个参数确定公式
		switch ((int)vParam[0])
		{
		case 1:
		{
				  if ((int)vParam.size() != 3)
				  {
					  LogErrFmtPrint("SkillPart::GetSkillDamgefix  damage formula error skillid=%d 公式1", skillid);
					  return 0;
				  }
				  resultDamage = skilllevel*vParam[1]*1.0/100 + vParam[2]*1.0/100;
				  break;
		}
		case 2:
		{
				  if ((int)vParam.size() != 3)
				  {
					  LogErrFmtPrint("SkillPart::GetSkillDamgefix  damage formula error skillid=%d 公式2", skillid);
					  return 0;
				  }

				  //Player * pPlayer = dynamic_cast<Player*>(m_pMaster);
				 // if (pPlayer)
				  if (pTargetCreature)
				  {
					  resultDamage = (skilllevel*vParam[1] * 1.0 / 100 + vParam[2] * 1.0 / 100) * pTargetCreature->GetAttr(C_MAX_HP);
				  }
				  else
				  {
					  LogDebugFmtPrint("skill type=2,but targetcreature =Null");
				  }
		}
		break;
		case 3:
		{
				  if ((int)vParam.size() != 3)
				  {
					  LogErrFmtPrint("SkillPart::GetSkillDamgefix  damage formula error skillid=%d 公式3", skillid);
					  return 0;
				  }

				  //Player * pPlayer = dynamic_cast<Player*>(m_pMaster);
				  if (pTargetCreature)
				  {
					  resultDamage = pTargetCreature->GetAttr(C_HP)*vParam[1] * 1.0 / 100 + vParam[2] * 1.0 / 100;
				  }
				  else
				  {
					  LogDebugFmtPrint("skill type=3,but targetcreature =Null");
				  }
		}
		case 4:
		{
				  if ((int)vParam.size() != 4)
				  {
					  LogErrFmtPrint("SkillPart::GetSkillDamgefix  damage formula error skillid=%d 公式4", skillid);
					  return 0;
				  }

				  //Player * pPlayer = dynamic_cast<Player*>(m_pMaster);
				 // if (pPlayer)
				  {
					  resultDamage = skilllevel*skilllevel*vParam[1]*1.0/100 + vParam[2]*1.0/100 * skilllevel + vParam[3]*1.0/100;
				  }
		}
		break;
		case 5:
		{
				  if ((int)vParam.size() != 5)
				  {
					  LogErrFmtPrint("SkillPart::GetSkillDamgefix  damage formula error skillid=%d 公式5", skillid);
					  return 0;
				  }

				  resultDamage = skilllevel*skilllevel*skilllevel*vParam[1] * 1.0 / 100 + vParam[2] * 1.0 / 100 * skilllevel*skilllevel + skilllevel*vParam[3] * 1.0 / 100 + vParam[4] * 1.0 / 100;
		}
		break;
		case 6:
		{
				  if ((int)vParam.size() != 4)
				  {
					  LogErrFmtPrint("SkillPart::GetSkillDamgefix  damage formula error skillid=%d 公式6", skillid);
					  return 0;
				  }

				  uint32_t level = m_pMaster->GetAttr(C_LEVEL);
				  resultDamage = level*level*vParam[1] * 1.0 / 100 + vParam[2] * 1.0 / 100 * level + vParam[3] * 1.0 / 100;
			
		}
		break;
		case 7:
		{
				  if ((int)vParam.size() != 5)
				  {
					  LogErrFmtPrint("SkillPart::GetSkillDamgefix  damage formula error skillid=%d 公式7", skillid);
					  return 0;
				  }
				  if (pTargetCreature)
				  {
					  resultDamage = pTargetCreature->GetAttr(C_MAX_HP)*vParam[1] * 1.0 / 100 + skilllevel*skilllevel*vParam[2] * 1.0 / 100 + skilllevel*vParam[3] * 1.0 / 100 + vParam[4] * 1.0 / 100;
				  }
		}
		break;
		case 8:
		{
				  if ((int)vParam.size() != 6 && m_pMaster->CreatureKind()!=CREATURE_PLAYER )
				  {
					  LogErrFmtPrint("SkillPart::GetSkillDamgefix  damage formula error skillid=%d 公式8", skillid);
					  return 0;
				  }

				  uint32_t prof = m_pMaster->GetAttr(C_PROF);
				  uint32_t attack = 0;
				  uint32_t def = 0;
				  if (prof == ECHARACTER_PROF_WARRIOR || prof == ECHARACTER_PROF_ASSASSIN) //物攻
				  {
					  attack = m_pMaster->GetAttr(C_AP);
					  def = m_pMaster->GetAttr(C_DP);
				  }
				  else
				  {
					  attack = m_pMaster->GetAttr(C_MP);
					  def = m_pMaster->GetAttr(C_MDP);
				  }

				  resultDamage = (attack - def*vParam[1] * 1.0 / 100)* vParam[2] * 1.0 / 100 + skilllevel*skilllevel*vParam[3] * 1.0 / 100 + skilllevel*vParam[4] * 1.0 / 100 + vParam[5] * 1.0 / 100;;

		}
		break;
		case 9:
		{
				  if ((int)vParam.size() != 3)
				  {
					  LogErrFmtPrint("SkillPart::GetSkillDamgefix  damage formula error skillid=%d 公式2", skillid);
					  return 0;
				  }

				  //Player * pPlayer = dynamic_cast<Player*>(m_pMaster);
				  // if (pPlayer)
				  if (pTargetCreature)
				  {
					  resultDamage = (skilllevel*vParam[1] * 1.0 / 100 + vParam[2] * 1.0 / 100) * pTargetCreature->GetAttr(C_MAX_MP);
				  }
				  else
				  {
					  LogDebugFmtPrint("skill type=2,but targetcreature =Null");
				  }
		}
			break;
		default:
			break;
		}
	}
	return resultDamage;
}


//uint32_t SkillPart::GetValueFromStringMula(uint32_t skillid, string str)
//{
//	VEC_INT32 outParam;
//	m_pMaster->GetFormula(str, outParam);
//	return GetValueFromFormula(skillid, outParam);
//}

//获取技能固定攻击值
int32_t SkillPart::GetSkillAttackfix(uint32_t skillid, uint32_t damageCount, Creature * pTargetCreature)
{
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillid);
	if (pConfig == NULL)
	{
		return 0;
	}

	if (damageCount + 1> pConfig->funcAttackValue.size()
		|| (int)pConfig->funcAttackValue[damageCount].size() <= 0)
	{
		return 0;
	}

	return GetValueFromFormula(skillid, (VEC_INT32&)pConfig->funcAttackValue[damageCount], pTargetCreature);
}

//获取技能固定伤害值
int32_t SkillPart::GetSkillHurtFix(uint32_t skillID, uint32_t damageCount, Creature * pTargetCreature)
{
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillID);
	if (pConfig == NULL)
	{
		return 0;
	}

	if (damageCount + 1 > pConfig->funcDamageValue.size()
		|| (int)pConfig->funcDamageValue[damageCount].size() <= 0)
	{
		return 0;
	}

	return GetValueFromFormula(skillID, (VEC_INT32&)pConfig->funcDamageValue[damageCount], pTargetCreature);
}

//获取技能附加攻击百分比
int32_t SkillPart::GetSkillHurtPercent(uint32_t skillID, uint32_t damageCount, Creature * pTargetCreature)
{
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillID);
	if (pConfig == NULL)
	{
		return 0;
	}

	if (damageCount + 1 > pConfig->funcAttackRate.size()
		|| (int)pConfig->funcAttackRate[damageCount].size() <= 0)
	{
		return 0;
	}

	return GetValueFromFormula(skillID, (VEC_INT32&)pConfig->funcAttackRate[damageCount], pTargetCreature);
}
//获取技能战斗力
float SkillPart::GetSkillFightValue(uint32_t skillID)
{
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillID);
	if (pConfig == NULL)
	{
		return 0;
	}

	if ((int)pConfig->strFightPower.size() <= 0)
	{
		return 0;
	}

	return GetValueFromFormula(skillID, (VEC_INT32&)pConfig->strFightPower);
}

//获取状态包参数值
int32_t  SkillPart::GetStateBagParam(uint32_t skillID, uint32_t bagIndex, uint32_t dameagePoint, Creature * pTargetCreature, uint32_t skillLev)
{
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillID);
	if (pConfig == NULL)
	{
		return 0;
	}

	if (bagIndex > pConfig->vStateBags.size()
		|| dameagePoint + 1>pConfig->vStateBags[bagIndex].vParameter.size()
		|| (int)pConfig->vStateBags[bagIndex].vParameter[dameagePoint].size()<= 0)
	{
		return 0;
	}

	return GetValueFromFormula(skillID, (VEC_INT32&)pConfig->vStateBags[bagIndex].vParameter[dameagePoint], pTargetCreature, skillLev);
}
//获取状态包时间参数
int32_t SkillPart::GetStateBagTimeParam(uint32_t skillID, uint32_t bagIndex, Creature * pTargetCreature)
{
	//stSkillInfo *pskill = GetSkillInfo(skillID);
	//if (!pskill)
	//{
	//	return 0;
	//}

	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillID);
	if (pConfig==NULL)
	{
		return 0;
	}

	if (bagIndex > pConfig->vStateBags.size()
		|| (int)pConfig->vStateBags[bagIndex].Time.size() <= 0)
	{
		return 0;
	}

	return GetValueFromFormula(skillID, (VEC_INT32&)pConfig->vStateBags[bagIndex].Time, pTargetCreature);
}
//获取技能附加伤害百分比
int32_t  SkillPart::GetSkillAttackPercent(uint32_t skillID, uint32_t damageCount, Creature * pTargetCreature)
{
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillID);
	if (pConfig == NULL)
	{
		return 0;
	}
	if (damageCount + 1 > pConfig->funcDamageRate.size() ||
		pConfig->funcDamageRate[damageCount].size()<0)
	{
		return 0;
	}

	return GetValueFromFormula(skillID, (VEC_INT32&)pConfig->funcDamageRate[damageCount], pTargetCreature);
	//return pConfig->funcDamageRate[damageCount][0];
}


//获取生物普通攻击技能
uint32_t SkillPart::GetNormalSkillID()
{
	std::vector<uint32_t> vec;
	GetNormalSkillID(vec);

	if (vec.size() == 1)
	{
		return vec[0];
	}
	else if (vec.size() > 1)
	{
		uint32_t index = Random(0, vec.size()-1);
		return vec[index];
	}
	return 0;
}

void SkillPart::GetNormalSkillID(std::vector<uint32_t>& vec)
{
	mapSkillInfo::iterator iter = m_mapskills.begin();
	for (; iter != m_mapskills.end(); ++iter)
	{
		if (iter->second._pSkillmeta->skilltype == enSkillType_Nomal &&
				iter->second.GetLeftCDTime() <= 0)
		{
			vec.push_back(iter->first);
		}
	}
}

//获取玩家当前等级可用技能列表,注意，不包含普通攻击
void SkillPart::GetCanUseSkillID(std::vector<uint32_t> & v)
{
	mapSkillInfo::iterator iter = m_mapskills.begin();
	for (; iter != m_mapskills.end(); ++iter)
	{
		if (iter->second._pSkillmeta->skilltype != enSkillType_Nomal
			&& iter->second._pSkillmeta->minLevel.size()>0
			&& iter->second._pSkillmeta->minLevel[0] <= (int32_t)m_pMaster->GetAttr(C_LEVEL))
		{
			v.push_back(iter->first);
		}
	}
}

//获取Monster当前等级可用技能列表,注意，不包含普通攻击
void SkillPart::GetMonsterCanUseSkillID(std::vector<uint32_t> & v)
{
	mapSkillInfo::iterator iter = m_mapskills.begin();
	for (; iter != m_mapskills.end(); ++iter)
	{
		if (iter->second._pSkillmeta->skilltype != enSkillType_Nomal
				&& iter->second.GetAILeftCDTime() <= 0 
				&& !IsPassiveSkill(iter->second._pSkillmeta))
		{
			v.push_back(iter->first);
		}
	}
}

bool SkillPart::IsPassiveSkill(const SkillCfg* pConfig)
{
	if (pConfig->type == enSkillTargetType_Reactive1
		|| pConfig->type == enSkillTargetType_Reactive2)
	{
		return true;
	}
	return false;
}

//获取技能所加战斗力
float SkillPart::GetAllSkillFightPower()
{
	float value = 0;
	mapSkillInfo::iterator iter = m_mapskills.begin();
	for (; iter != m_mapskills.end();++iter)
	{
		value += iter->second._fightValue;
	}

	return value;
}

//重置所有技能cd
void  SkillPart::RefreshAllSkillCDTime()
{
	mapSkillInfo::iterator iter = m_mapskills.begin();
	for (; iter != m_mapskills.end(); ++iter)
	{
		iter->second._cdTimeStamps = 0;
	}
}

//判断状态包是否命中
bool SkillPart::IsHitStateBag(Creature *pSource,Creature * ptarget, SkillCfgStateBag & cfgStatePra)
{
	float rate = 0.0f;
	if (!ptarget)
	{
		rate = cfgStatePra.Rate / 10000.0;
		uint32_t tmpRate = Random(1, 100);
		if (tmpRate > rate * 100)
		{
			return false;
		}
		return true;
	}
	bool isFuShu = false;
	int32_t diffLev = pSource->GetAttr(C_LEVEL) - ptarget->GetAttr(C_LEVEL);
	if (diffLev<0)
	{
		isFuShu = true;
	}
	diffLev = diffLev > 0 ? diffLev : -diffLev;
	const AttributeSuppressCfgInfo *pSuppress = g_GetAttributeSuppressCfgTable()->GetAttributeSuppressCfgInfo(diffLev);

	int32_t critSuppress = 0;
	if (pSuppress)
		critSuppress = pSuppress->stateSuppress;

	if (isFuShu)
	{
		critSuppress = -1 * critSuppress;
	}


	Creature * pAttrSource = pSource;

	if (cfgStatePra.Type == enStateType_Add) //直接用概率
	{
		rate = cfgStatePra.Rate/10000.0f;
	}
	else if (cfgStatePra.Type == enStateType_None)
	{
		rate = cfgStatePra.Rate / 10000.0f + critSuppress / 10000.0f;
	}
	else if (cfgStatePra.Type == enStateType_Control)
	{
		rate = cfgStatePra.Rate / 10000.0f + critSuppress / 10000.0f + pAttrSource->GetAttr(C_CONTROLDAWN) / 10000.0f - ptarget->GetAttr(C_CONTROLUP) / 10000.0f;
	}
	else if (cfgStatePra.Type == enStateType_ContinuDamage)
	{
		rate = cfgStatePra.Rate / 10000.0f + critSuppress / 10000.0f + pAttrSource->GetAttr(C_PERSISTDOWN) / 10000.0f - ptarget->GetAttr(C_PERSISTUP) / 10000.0f;
	}
	else if (cfgStatePra.Type == enStateType_Week)
	{
		rate = cfgStatePra.Rate / 10000.0f + critSuppress / 10000.0f + pAttrSource->GetAttr(C_WEAKDOWN) / 10000.0f - ptarget->GetAttr(C_WEAKUP) / 10000.0f;
	}
	else if (cfgStatePra.Type == enStateType_Move)
	{
		rate = cfgStatePra.Rate / 10000.0f + critSuppress / 10000.0f + pAttrSource->GetAttr(C_DISPLACEDOWN) / 10000.0f - ptarget->GetAttr(C_DISPLACEUP) / 10000.0f;
	}
	else if (cfgStatePra.Type == enStateType_ForbidFa)
	{
		rate = cfgStatePra.Rate / 10000.0f + critSuppress / 10000.0f + pAttrSource->GetAttr(C_SILENCEDOWN) / 10000.0f - ptarget->GetAttr(C_SILENCEUP) / 10000.0f;
	}

	uint32_t tmp = Random(1, 100);
	if (tmp>rate*100)
	{
		return false;
	}

	return true;
}


//获取等级压制率
int32_t SkillPart::GetLevelSuppress(Creature * pSource, Creature * ptarget)
{
	bool isFuShu = false;
	int32_t diffLev = pSource->GetAttr(C_LEVEL) - ptarget->GetAttr(C_LEVEL);
	if (diffLev<0)
	{
		isFuShu = true;
	}
	diffLev = diffLev > 0 ? diffLev : -diffLev;
	const AttributeSuppressCfgInfo *pSuppress = g_GetAttributeSuppressCfgTable()->GetAttributeSuppressCfgInfo(diffLev);

	int32_t critSuppress = 0;
	if (pSuppress)
		critSuppress = pSuppress->levelSuppress;

	if (isFuShu)
	{
		critSuppress = -1 * critSuppress;
	}
	return critSuppress;
}
